VRF Tutorial

VRF is a full compliance XML based language used to build for representing interactive 3D and 2D with VR support. It includes its own scripting language for software design, and a format support for 3D models. VRF allows you to build a 3D environment without doing any 3D modeling. You can integrate many kinds of media right into a VRF, including sound, animation, 2D graphics, and text. Building 3D environment is actually very similar to building in the real world using familiar pieces such as simple wooden units or even two-by-fours from the local lumberyard. In VRF, there are sets of predefined 3d objects that you can put together to build a house, or a waterfall, or anything you desire. A VRF file has 2 major sections: the globals and the design. The globals is the section where you set attributes for the entire 3D environment, such as the map layers dimensions, atmosphere light and sound, the sky texture, etc. The design is the section where you can customize your 3d objects, and where you create your actual global map. The map layers are the heart of a VRF file, where you use different kinds of 3d objects (represented by double ASCII characters) to build a 3D environment. Each unit typically occupies a space of 256 x 256 x 256 (pixels). Units are arranged into a grid pattern to create each horizontal layer of a VRF. Layers are stacked on top of each other to create multi-layers VRF´S. This tutorial will take you step-by-step through the process of creating a VRF. After you have completed your first one, you may wish to use more advanced VRF features.

Before you begin the tutorial, there are two things you will need to do:
  • Download and install the VRGrid application
  • Get a free Github account since this tutorial will use Github for hosting
Getting Started

After creating a Github account create a repository. In your Github profile page go to “Repositories” then “New” and fill in the form. After your repository as been created we need to create a static host adress for it, to do that enter your repository you will have a “master” branch we will create a “gh-pages” branch. So select the “Branch” button and you will see “Find or create a branch” type in gh-pages and create. After that you also will have a Github https adress for that repository. To see your repository web adreess go to the repository “Settings” and you will find it under “Github Pages” “ You shoud see “Your site is published at "https://yourusername.github.io/yourrepositoryname/"”. That will be your web adress from now. Thats it and you are all set to go, from now on we will use the “gh-pages” branch of the repository to make and edit our files. If you want to use a standard code editor you can also you'll want to use software that displays all ASCII characters in monospacing and can do column editing. PTSource Developer Platform as support and syntax highlighting for VRF files. But in this tutorial we will only use the Github web editor. Se let´s start.

In the “gh-pages” branch of you repository create a new file named myfirstvrf.vrf

Go ahead and type the following lines in that file to get started :

<vrf>
<globals>
</globals>
<design>
</design>
</vrf>
Everything in a VRF file must be bounded by the <vrf> and </vrf> tags.

The <globals> part of the VRF

The <globals> part of the VRF contains several XML tags that apply to the entire VRF.

The <title> tag. The <title> tag holds the title of the VRF. The title text will be displayed at the bottom of VRGrid.

Put the following code between the <globals> tags in your VRF file:

<title name="My VRF Test" />
The <lib> tag. The <lib> tag lets VRGrid know what library of 3d objects and textures to use to display the VRF. The first time VRGrid encounters a new library, the library is downloaded and cached. The next time VRGrid encounters the same library, VRGrid will check if it is cached before attempting to download it.

Put the following code between the <globals> tags in your VRF file:

<lib href="https://ptsource.github.io/VRGrid/libs/basic.vlib"/>

The <map> tag. The <map> tag tells VRGrid what size your VRF is going to be. VRF´S are measured in units, (columns, rows, levels). When you are building a VRF, remember that whenever you change the dimensions of your map by adding new layers, columns,or rows, you will have to change the dimensions in the <map> tag as well.We are going to make a VRF that is 9 units wide, 9 units long, and 1 unit high.

Put the following code between the <globals> tags in your VRF file.

<map dimensions="(9,9,1)" />

The <assets> tag. When cloud hosting the VRF file the assets tag sets the include directory for files (i.e., VRI'S, textures, sounds, script imports). This is usefull for sharing files and media between multiple VRF´S.

Put the following code between the <globals> tags in your VRF file:

<assets href="https://ptsource.github.io/VRGrid/assets/" />
The <sky> tag .The <sky> tag sets an image to be used as the background for your VRF. This texture will appear anywhere there aren't any units visible. If you don't put a ceiling on your VRF, the texture defined in the <sky> tag will appear in the sky. If you leave any holes in your walls or floors, then the <sky> texture will be seen there. If you prefer, you can set a color for the sky rather than a texture. The color is expressed by red, green, and blue values between 0 to 255. For example, pure red would be expressed as color=”(255,0,0)“, pure blue is color=”(0,0,255)“, and pure green would be color=”(0,255,0)“. All other colors can be expressed as combinations of red, green, and blue. You can also set the brightness of the sky in the <sky> tag. Brightness is expressed as a whole number percentage. If you don't specify brightness, the default level is 100%. If you leave out the <sky> tag altogether, the background will default to the sky texture specified in the library. Remember, if your image file isn't in the same folder as your VRF file, then you also need to specify the path to your image: <sky texture= “folder/image.vri -or- URL” /> the file must be located in a sub-folder of the path defined in the assets tag.

Put the following code between the <globals> tags in your VRF file:

<sky texture="images/clouds.gif" brightness="90%" />

The <ground> tag. The <ground> tag specifies a texture (or color) to be used on the ground plane of your VRF. If you use the <ground> tag, then you won't have to supply a solid floor of 3d objects in your map. The ground will be the same dimensions as your map. If your map is 5 units by 8 units, then your ground will be that same size as well. You can specify either a texture or a color with which to fill the ground plane. If you leave the <ground> tag out, there will be no ground plane displayed in your VRF, and you will have to supply a solid floor made of 3d objects in order to keep your visitors from falling endlessly through virtual space. If you want to use the default ground texture specified by the library, then simply include an empty <ground> tag in your VRF file: <ground />.

Put the following line of code between the <globals> tags in your VRF file:

<ground texture="images/dirt.gif" />

The <atmosphere> tag. The <atmosphere> tag has two attributes: brightness and color. Brightness defines how bright your VRF will appear to be in areas where you haven't placed any other lights. Brightness is expressed as a whole number percentage. If you set your atmosphere light relatively low, say around 50%, then you will have more room to play with lighting effects later. If you don't need that kind of flexibility, go to globals and set brightness at or close to 100%. The color attribute allows you to specify what color the light is in your VRF. Brightness defaults to 100%, if not otherwise specified. Color defaults to white, or (255,255,255).

Put the following code between the <globals> tags in your VRF file:

<atmosphere brightness="100%" />

The <ambience> tag. The <ambience> tag specifies a sound file that will play throughout your VRF. The ambience sound will be heard at the same volume throughout the entire VRF. The sound can either be looped continuously or played at random intervals with the playback attribute. If playback=“random”, you can also specify a range of delay times between playbacks. Delay times are measured in seconds, and are measured from the time that the sound begins, rather than when it ends. For example, if your sound is 5 seconds long, playback=“random”, and delay=“5..10”, then sometimes the sound will play back to back, (as the length of the sound file is the same as the minimum delay time), and no more than 5 seconds will ever elapse between when the sound ends and when it begins again. (The maximum delay time, 10 seconds, minus the length of the sound itself, 5 seconds, leaves a maximum silence of 5 seconds.) The default values for these attributes are volume=“100%”, playback=“looped”, delay=“5..10”.

Put the following code between the <globals> tags in your VRF file:

<ambience file="sounds/waves.wav" volume="65%" playback="looped" />

The <devel> tag. <devel> is an optional tag you can use to get more information about errors in your VRF. VRGrid by default ignores these errors as much as possible but if you include the <devel> tag you will get more information that will help you to locate and correct errors, also when the <devel> tag is avalible the code will be shown using the “V” key. So if you want to use the <devel> tag add the following line of code in your <globals> tag:

<devel />

The complete xml globals code for this tutorial should look like this:

<vrf>
<globals>
<title name="My VRF Test" />
<lib href="https://ptsource.github.io/VRGrid/libs/basic.vlib"/>
<assets href="https://ptsource.github.io/VRGrid/assets/" />
<map dimensions="(9,9,1)" />
<sky texture="images/clouds.gif" brightness="90%" />
<ground texture="images/dirt.gif" />
<atmosphere brightness="100%" />
<ambience file="sounds/waves.wav" volume="65%" playback="looped"/>
<devel />
</globals>
<design>
</design>
</vrf>  

The <design> part of the VRF

The <design> tag. The design of a VRF file is where you finally get to make the map itself. There are five main activities that are handled in the <design> tags are:

  1. Customizing 3d objects
  2. Creating the map
  3. Creating popups
  4. Assigning image maps
  5. Assigning enters and exits

First we will create a simple map and an enter. The map is made up of individual layers that act just like stories of a building. Each layer in a VRF must have the same number of rows and columns. If you need to add extra rows or columns to a VRF you have already been working on, you will need to add those rows or columns to every layer in the VRF. Each layer in a VRF is bounded by the <layer>…</layer> tags. The <layer> tag has just one attribute: number, number=“1” refers to the bottom layer of a VRF, just like floors of a building. Any character between the <layer> tags will be interpreted as a unit. All units occupy the space of a cube with 256 pixels in every dimension (256 x 256 x 256).

For this first map we will use just two kinds of 3d objects. You can find a complete list of 3d objects reference in the VRGrid menu under “Libraries”. We will use :

  • The full 3d object ”##“ The full 3d object is a solid cube, filling up the entire 256 x 256 x 256 unit space.
  • The empty unit ”..“ Nothing but virtual thin air. The empty unit is just a place holder that keeps your maps looking like easy-to-read grids.

Put the following code between the <design> tags in your VRF file:

<layer number="1">
     ## ## ## .. .. .. ## ## ## 
     ## .. .. .. .. .. .. .. ##
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ##  
     ## .. .. .. .. .. .. .. ##  
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ##  
     ## ## ## ## ## ## ## ## ## 
</layer>

The <enter> tag . You must always specify at least one ennter for your VRF. The enter doesn't look like anything, it is just the place in the VRF where your visitors will first land. The <enter> tag has three attributes: location, name, and angle. An <enter> tag can be placed anywhere within the <design> tag. Some prefer to put their <enter> tags immediately following the layer in which they occur, others prefer to keep all of their <enter> tags together just before the closing </design> tag after all of the layers have been defined. In this tutorial we will keep them together at the end of the <design>. Our first VRF will only have one layer and one enter. The location is specified as an (x,y,z) coordinate, measured in units (with 1,1,1 being in the top left (or northwest) corner of the bottom layer.) The name attribute allows you to name each enter, so that you can refer to them later. They act sort of like targets in HTML. Every VRF must have one enter named “default”. The angle attribute defines what direction your visitors will be facing when they enter the VRF. The angle parameter has 2 values, turn and tilt, specified in whole number degrees. The first value specifies what direction (north, south, east, west, or somewhere in between) your visitors will face. Possible values range from 0 to 359. The second value specifies whether they will be looking up or down, with possible values of -90 to 90. The default value is “0,0” which will leave your visitors facing north, and parallel to the horizon. A value of “90,0” will set your visitors facing directly east, “180,45” will leave them facing south, and 45 degrees up into the “air”, etc.

Put the following code after the </layer> tag in your VRF file:

<enter location="(5,8,1)" name="default" angle="0,0" />

Congratulations! You now have a fully functioning VRF! Save your Github file “myfirstvrf.vrf” in your Github repository and open VRGrid, type “G” or select “Open VRGrid URL” from the “File” menu and paste : "https://yourusername.github.io/yourrepositoryname/myfirstvrf.vrf". You will find yourself in a room with 4 walls and no ceiling. You should see your sky texture overglobals, and the ground texture underfoot. You will also see the sky texture in the open space in the wall in front of you. Go to the edge and look over.

The complete xml code for this VRF should look like this :

<vrf>
<globals>
<title name="My VRF Test" />
<lib href="https://ptsource.github.io/VRGrid/libs/basic.vlib"/>
<assets href="https://ptsource.github.io/VRGrid/assets/" />
<map dimensions="(9,9,1)" />
<sky texture="images/clouds.gif" brightness="90%" />
<ground texture="images/dirt.gif" />
<atmosphere brightness="100%" />
<ambience file="sounds/waves.wav" volume="65%" playback="looped"/>
<devel />
</globals>
<design> 
<layer number="1">  
     ## ## ## .. .. .. ## ## ## 
     ## .. .. .. .. .. .. .. ##
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ##  
     ## .. .. .. .. .. .. .. ##  
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ##  
     ## ## ## ## ## ## ## ## ## 
</layer>  
<enter location="(5,8,1)" name="default" angle="0.0" />
</design>
</vrf>

As you can see it´s easy to get your show on the road, you can find all 13 tutorial files in VRGrid Github repository here VRGrid Github as well in you VRGrid menu under “Tutorial and Samples” just load them in VRGrid an type “V” to view all the code, full samples are also included.

Multiple Layers

So lets make this simple room we've created a little taller and give it a ceiling. The ceiling object "--" (that's a hyphen, not an underline) is 32 pixels thick and fills the top of the unit space. Ceiling objects also happen to make great floors for the layer above them!

Numbering layers

Layers in a VRF have to be numbered. Numbering is an easy way to keep track of what layer of a VRF you are working on, but it also means that if you add any new layers to anywhere other than the top of a VRF, you have to go through and change all of your layers numbers.

Make a taller VRF Add the following code to your VRF file, after the layer that you've already made.

<layer number="2"> 
     ## ## ## -- -- -- ## ## ## 
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## ## ## ## ## ## ## ## ## 
</layer>
Now we have changed the dimensions of our VRF, so we will have to change the <map> tag as well. Change your <map> tag to read:
<map dimension="(9,9,2)" />
Lets also change the title of this VRF to My Tall VRF Test. Change the <title> tag to read like this:
<title name="My Tall VRF Test" />
Now save it and open it in VRGrid. You should have a tall room with a ceiling and an opening in front of you.
<vrf>
<globals>
<title name="My Tall VRF Test" />
<lib href="https://ptsource.github.io/VRGrid/libs/basic.vlib"/>
<assets href="https://ptsource.github.io/VRGrid/assets/" />
<map dimensions="(9,9,2)" />
<sky texture="images/clouds.gif" brightness="90%" />
<ground texture="images/dirt.gif" />
<atmosphere brightness="100%" />
<ambience file="sounds/waves.wav" volume="65%" playback="looped"/>
<devel />
</globals>
<design> 
<layer number="1">  
     ## ## ## .. .. .. ## ## ## 
     ## .. .. .. .. .. .. .. ##
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ##  
     ## .. .. .. .. .. .. .. ##  
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ##  
     ## ## ## ## ## ## ## ## ## 
</layer>  
<layer number="2"> 
     ## ## ## -- -- -- ## ## ## 
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## ## ## ## ## ## ## ## ## 
</layer>
<enter location="(5,8,1)" name="default" angle="0.0" />
</design>
</vrf>

Navigation in Multi-Layer VRF´S

Visitors to your VRF´S can't fly through them. VRF´S have gravity, so if you want your visitors to be able climb to the upper levels of your VRF, then you will have to provide a path for them to do so. The half object “hh” The half object is just the bottom half of a full object. The nramp object “NN” The nramp object is a ramp that rises to the height of a full object, going up towards the north. The nbottomramp object “kk” The nbottomramp object is a ramp that rises to the height of a half object, going up towards the north. The ntopramp object “KK” The ntopramp object is a ramp that rises from the height of a half object to the height of a full object, going up towards the north. Provide a path onto the roof of your VRF. Change layer 1 of your My Tall VRF Test to look like this:

<layer number="1">
     ## ## ## .. .. .. ## ## ##
     ## .. .. .. .. .. .. .. ##
     ## ## .. .. .. .. .. .. ##
     ## ## .. .. .. .. .. .. ## 
     ## KK .. .. .. .. .. .. ##  
     ## hh .. .. .. .. .. .. ## 
     ## kk .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ## 
     ## ## ## ## ## ## ## ## ##
</layer>
Change layer 2 of your My Tall VRF Test to look like this:
<layer number="2">
     ## ## ## -- -- -- ## ## ##
     ## -- -- -- -- -- -- -- ## 
     ## NN -- -- -- -- -- -- ## 
     ## .. -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ## 
     ## ## ## ## ## ## ## ## ## 
</layer>
Now save it and open it in VRGrid. You should now be able to climb the ramps up to the roof.
<vrf>
<globals>
<title name="My Tall VRF Test" />
<lib href="https://ptsource.github.io/VRGrid/libs/basic.vlib"/>
<assets href="https://ptsource.github.io/VRGrid/assets/" />
<map dimensions="(9,9,2)" />
<sky texture="images/clouds.gif" brightness="90%" />
<ground texture="images/dirt.gif" />
<atmosphere brightness="100%" />
<ambience file="sounds/waves.wav" volume="65%" playback="looped"/>
<devel />
</globals>
<design>
<layer number="1">
     ## ## ## .. .. .. ## ## ##
     ## .. .. .. .. .. .. .. ##
     ## ## .. .. .. .. .. .. ##
     ## ## .. .. .. .. .. .. ## 
     ## KK .. .. .. .. .. .. ##  
     ## hh .. .. .. .. .. .. ## 
     ## kk .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ## 
     ## ## ## ## ## ## ## ## ##
</layer>
<layer number="2">
     ## ## ## -- -- -- ## ## ##
     ## -- -- -- -- -- -- -- ## 
     ## NN -- -- -- -- -- -- ## 
     ## .. -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ## 
     ## ## ## ## ## ## ## ## ## 
</layer>
<enter location="(5,8,1)" name="default" angle="0.0" />
</design>
</vrf> 

The <create> tag. Creating and changing textures

All of the VRF objects are assigned particular textures, and sometimes sounds or other attributes. With the <create> tag, you can customize many of these features. The <create> tag works by telling VRGrid to take a object it already knows, change a few things about it, and give it a new ASCII unit to represent the new object in the map. Each kind of object that is used in a VRF file has a number of “sides” that make up its shape. You can change the texture of each of these sides with the <create> tag. For example, the full object has 6 sides corresponding to the six sides of the cube. They are refered to as “n, s, e, w, top, and bottom”, with n,s,e, and w, corresponding to north, south, east, and west. To find out the sides that make up each object check the reference guides. Lets take a look at a sample <create> tag:

<create unit="aa" vrobj="basic:full">
<side name="n,s,e,w" texture="images/brick.gif" />
</create>
This tag tells VRGrid that we are going to make a new object, which will be referred to in the map as the unit with the ASCII character “aa”, and which will be shaped like a full object from the Basic library. Then we tell VRGrid to change the texture on the 4 sides of the cube to be the file “brick.gif”, located in the “images” folder specified with the <assets> tag. Note that the “top” and “bottom” parts of the object haven't been changed, and will appear with the default texture.

Image File Formats.

VRGrid supports GIF files (including animated or transparent GIFs), JPEG files and VRI textures generated from PNG or APNG images, maximum image size is 1024px X 1024px.

Syntax Rules

There are some syntax details you'll need to keep in mind. <create> tags are placed in the <design>, before your first layer. If you want to change all of the sides of a object to be a single texture, you can use “*” to refer to all sides at once:

 
<side name="*" texture="images/brick.gif" />
would change all parts of a object to the brick texture. In the object attribute, you should refer to the object type by its name and library “basic:full” or by its default ASCII unit ”##“. You can also reuse the ASCII unit that are assigned as defaults. For example, if you aren't going to use any unaltered full objects in your VRF, then you can assign the ”##“ unit to one of your changed objects:
<create unit="##" vrobj="basic:full">
<side name="*" texture="images/brick.gif" />
</create>
Now everytime you use the ”##“ unit in your map, you will get full objects that are textured with brick.gif, rather than the default texture. All objects have default textures that are included in the library. If you want to use one of these textures on a different side or different object, you can do so by preceeding the texture name with a ”@“.
<create unit="#" vrobj="#">
<side name="top" texture="@basic:clouds.gif" />
</create>
This would put the texture clouds.gif of the basic library on the top side of the full object.

Texture styles

By default, textures will be “tiled” to fill the part in question when you change a texture. If your texture is 128 x 128 pixels, and the side you are placing it on is 256 x 256, then the texture will be tiled to the appropriate size to fit the side.

You also have a couple of other options if you use the style attribute in the <side> tag. With style, you can set the texture to scale up to fill the side or you can set it to strech to fill the side, style=“scaled” will simply grow the texture to the size of a full object (256 x 256), and apply that texture to the side in question, style=“stretched” will lay the texture stretched to fit the side in question.

Texture projection

On some objects, textures may not always appear exactly as you expected. This happens on curved objects, like spheres, domes or curvein and curveout objects. To make a long story short, the way VRGrid usually projects textures onto objects just doesn't work well for these curved objects. For these objects, it works best for the texture to be projected from just one side, and you can specify which side with the projection attribute. Possible values are “top|bottom|north|south|east|west”. Projection is only necessary with textures that are “tiled” or “scaled” onto curved objects. “stretched” textures do not need the projection attribute.

Texture orientation

Occasionally you may want to change the orientation of a texture on a side. For instance, you may want it to display upside-down. You can achieve this by adding an angle attribute to the <create> tag. Possible values for the angle attribute range from 0-359. The texture will be rotated in a clockwise direction, angle=“180” would turn the texture 180 degrees clockwise, in effect turning it upside down.

Color and effects (clarity)

You can also use the <create> tag to assign a color to a side of a object, rather than a texture:

<side name="name" color="(red,green,blue)" />
You can also set a side transparency effects with clarity:
<side name="top" texture="painting.gif" clarity="50%" />

The faces attribute

Faces specifies whether a texture is displayed on one, both, or none of the sides of a polygon. The default value is faces=“1” which means that textures are applied to just one side of a polygon. So with a full object in its default state, you can see the textures from the outside of the object. But if you were to step inside the object itself, you would not see anything, because the textures are not displayed on the “inside” sides of the polygons. But if you specify faces=“2”, then the textures will be displayed on both sides of each polygon. This is particularly useful if you use clarity effects on one side of a object. For instance, if you use a texture with the clarity effect on the south side of a full object, and you use faces=“2” for all the other sides, then you will be able to see the inside of the object when you look through the south side. The faces attribute can also be used to make polygons invisible, by using faces=“0”. This will prevent textures from being displayed on both sides of the polygon, making it invisible. You still won't be able to walk through it though. The faces attribute goes in the <side> tag.

Solidity

The solid attribute determines whether or not your visitors will collide with that particular side of a object. If solid=“no”, then they will be able to walk right through that side. The default value is solid=“yes”.

So the syntax for the entire <side> tag is as follows:

<side name="name" texture="folder/image.gif"
color="(r,g,b)" style="tiled|stretched|scaled"
projection="top|bottom|north|south|east|west"
faces="0|1|2" solid="yes|no" clarity="clarity%"
angle="0-359" />

The loader texture

When a visitor first enters the VRF, it may take a few seconds to download the custom textures that you have assigned to your objects. If VRGrid is ready to display a object, but the texture has not finished downloading, then a loader texture will be displayed until the custom texture arrives. Every library has a loader texture associated with it that will be used by default, but you can also assign a different texture to act as the loader.

The <loader> tag goes in the globals of the VRF file and has just one attribute.

<loader texture="image-file-path -or- URL" />
You can also use different colors as loaders on specific objects by using the color attribute in the <create> tag. If a <create> tag has both a texture and color attribute, then the color will be displayed as a loader until the image file arrives. This feature is useful if you want to try to approximate your final textures before they download. For instance, if one of your textures looks like water, then you could take a blue color from that texture and use it instead of the loader texture while the full texture downloads.

Downloading textures

Textures will be downloaded in the order in which they appear in the VRF file, so it is a good idea to put the <create> tags for the objects that appear near enter location to your VRF first in your VRF file. This way your visitors can begin to see your VRF the way you intended without having to wait for the entire download to finish. Or you can use the <load> tag to force VRGrid to load textures in a different order. When VRGrid encounters a <load> tag in a VRF file, it will load that image at that time, before moving on to the next <create> tag.

The syntax for load looks like this:

<load texture="folder/image.gif" />

Change a texture in your VRF

Put the following code in My Tall VRF Test, just after the <design> tag:

<create unit="##" vrobj="basic:full">
<side name="n,s,e,w" texture="images/pinkmarble.gif" />
</create>
<create unit="--" vrobj="basic:ceiling">
<side name="bottom" texture="@basic:edgetop.gif" />
</create>

Now save it and open it in VRGrid. The walls and the ceiling of your VRF should appear textured. If you go up onto the roof, however, you will see that the top of the ceiling objects haven't changed.

<vrf>
<globals>
<title name="My Tall VRF Test" />
<lib href="https://ptsource.github.io/VRGrid/libs/basic.vlib"/>
<assets href="https://ptsource.github.io/VRGrid/assets/" />
<map dimensions="(9,9,2)" />
<sky texture= "images/clouds.gif" brightness="90%" />
<ground texture="images/dirt.gif" />
<atmosphere brightness="100%" />
<ambience file="sounds/waves.wav" volume="65%" playback="looped"/>
<devel />
</globals>
<design>
<create unit="##" vrobj="basic:full">
        <side name="n,s,e,w" texture="images/pinkmarble.gif" />
</create>
<create unit="--" vrobj="basic:ceiling">
        <side name="bottom" texture="@basic:edgetop.gif" />
</create>
<layer number="1">
     ## ## ## .. .. .. ## ## ##
     ## .. .. .. .. .. .. .. ##
     ## ## .. .. .. .. .. .. ##
     ## ## .. .. .. .. .. .. ## 
     ## KK .. .. .. .. .. .. ##  
     ## hh .. .. .. .. .. .. ## 
     ## kk .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ## 
     ## ## ## ## ## ## ## ## ##
</layer>
<layer number="2">
     ## ## ## -- -- -- ## ## ##
     ## -- -- -- -- -- -- -- ## 
     ## NN -- -- -- -- -- -- ## 
     ## .. -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ## 
     ## ## ## ## ## ## ## ## ## 
</layer>
<enter location="(5,8,1)" name="default" angle="0.0" />
</design>
</vrf>

The <create> tag. Orientation

In addition to changing textures, the <create> tag can also be used to change the orientation of a object, or turn it to face another direction. Orientation is accomplished by specifying two different values. First, you specify what direction you want the top of the object to face (up,down,north,south,east, or west). Then you specify an angle of rotation around that axis.Lets look at a new object called the curvein object, and turn it around to see how orientation works.

The curvein object looks like a full object that has been “scooped out” to be concave on the top and south sides. Now if you want to turn the curvein object around so that the scooped out side faces the top and north, you would use the following tag:

<create unit="AA" vrobj="basic:curvein">
<param orient="up,180" />
</create>
Now every time VRGrid encounters an “AA” in the map, it will take a curvein object, leave its top pointing “up”, and turn it 180 degrees clockwise, (around the Y axis) making the curved side of the object face up and north. Now, if you were standing to the south of a curvein object, and you wanted to tip it over to the right, so its top faced east, you would use this code:
<create unit="AA" vrobj="basic:curvein">
<param orient="east,0" />
</create>

So VRGrid will make the top of the object face “east”, and will rotate it “0” degrees around that axis. Now imagine that you want the “scooped out” part to face down and east. You'll need to point the top of the object towards the “east”, and then rotate “270” degrees. That is a 270 degree clockwise rotation, if you were looking at the original top of the object, which is now pointing east. Rotation is limited to values of 0, 90, 180, or 270. Rotation is always clockwise around what was originally the y axis. Imagine that you are standing on the top of the object, and you remain there as the object is tilted to the “east”. You are now standing on the east side of the object, looking at what used to be the top of the object. The rotation will take place in a clockwise direction from where you are standing. Having a physical object to play with on your desk may be of some help. Here are some examples to help you visualize all this topsy-turvy-ness. Without any rotation, objects are designed to look “right” to a visitor who is facing north. This is just a general rule that hopefully will make building a little easier. For instance, the curvein and curveout objects both have their curves on the south side, so that you can see them when you are facing north. The front door of the house objects (in the Village objectset) all face south, so that they look correct to a visitor who is facing north.

A note about ramps

In the Basic library, we have gone ahead and provided north, south, east and west orientations of the ramp objects, just to make life a little easier. So to get a ramp that goes up to the south, you can just use the sramp object, rather than having to use an orient attribute on an nramp object.

Change the orientation of a object

First, lets just put a few different curvein objects in your vrf just to see how they work.

Put the following code in My Tall VRF Test, just after the <design> tag:

<create unit="AA" vrobj="basic:curvein">
        <param orient="east,0"/>
</create>
<create unit="BB" vrobj="basic:curvein">
        <param orient="west,0"/>
</create>
<create unit="CC" vrobj="basic:curvein">
        <param orient="north,90"/>
</create>
<create unit="DD" vrobj="basic:curvein">
        <param orient="270,90"/>
</create>

Change layer 1 code in My Tall VRF Test look like this:

<layer number="1">
     ## ## ## .. .. .. ## ## ##
     ## AA .. .. .. .. .. BB ##
     ## ## .. .. .. .. .. .. ## 
     ## ## .. .. .. .. .. .. ##
     ## KK .. .. .. .. .. .. ##
     ## hh .. .. .. .. .. .. ##
     ## kk .. .. .. .. .. .. ##
     ## DD .. .. .. .. .. CC ##
     ## ## ## ## ## ## ## ## ##  
</layer>

Now save it and open it in VRGrid. Take a look at how each orientation attribute changed the different curvein objects.

<vrf>
<globals>
<title name="My Tall VRF Test" />
<lib href="https://ptsource.github.io/VRGrid/libs/basic.vlib"/>
<assets href="https://ptsource.github.io/VRGrid/assets/" />
<map dimensions="(9,9,2)" />
<sky texture= "images/clouds.gif" brightness="90%" />
<ground texture="images/dirt.gif" />
<atmosphere brightness="100%" />
<ambience file="sounds/waves.wav" volume="65%" playback="looped"/>
<devel />
</globals>
<design>
<create unit="AA" vrobj="basic:curvein">
        <param orient="east,0"/>
</create>
<create unit="BB" vrobj="basic:curvein">
        <param orient="west,0"/>
</create>
<create unit="CC" vrobj="basic:curvein">
        <param orient="north,90"/>
</create>
<create unit="DD" vrobj="basic:curvein">
        <param orient="270,90"/>
</create>
<create unit="##" vrobj="basic:full">
        <side name="n,s,e,w" texture="images/pinkmarble.gif" />
</create>
<create unit="--" vrobj="basic:ceiling">
        <side name="bottom" texture="@basic:edgetop.gif" />
</create>
<layer number="1">
     ## ## ## .. .. .. ## ## ##
     ## AA .. .. .. .. .. BB ##
     ## ## .. .. .. .. .. .. ## 
     ## ## .. .. .. .. .. .. ##
     ## KK .. .. .. .. .. .. ##
     ## hh .. .. .. .. .. .. ##
     ## kk .. .. .. .. .. .. ##
     ## DD .. .. .. .. .. CC ##
     ## ## ## ## ## ## ## ## ##  
</layer>
<layer number="2">
     ## ## ## -- -- -- ## ## ##
     ## -- -- -- -- -- -- -- ## 
     ## NN -- -- -- -- -- -- ##
     ## .. -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## ## ## ## ## ## ## ## ## 
</layer>
<enter location="(5,8,1)" name="default" angle="0.0" />
</design>
</vrf>

Linking

The ability to make hyperlinks between information sources is arguably the most important feature of the Web. VRF´S are no different in this respect than Web pages. Links are accomplished in VRF by naming enters and exits in your file, and pointing them at each other or at outside VRF´S. Links can occur anywhere in a VRF. You can place an exit on any object, including an empty object. Traditionally, however, exits are used in conjuction with the portal object. When a visitor to your VRF rolls their mouse over an exit, the destination title will appear just below the cursor, to let them know where the link will take them.

The portal object ”@@“

The portal object is used to indicate a link. By default, a portal object is linked to VRGrid base portal. You can link the portal to any VRF by using an <exit> tag.

The <exit> tag

<exit location="(column,row,layer)"
href="file_name#enter_name"
trigger="click on,step on" text="text"
target="destination name" />

Like the <enter> tag, the <exit> tag can be placed anywhere within the <design> tags. The <exit> tag has five attributes: location, href, trigger, target, and text. Location is the (x,y,z) coordinate at which the exit occurs, with (1,1,1) being in the top left or northwest corner of the bottom layer. Href is where the link leads to, expressed as the destination's file name, followed by the enter name, separated by a ”##“. Trigger defines how the exit may be activated, either by clicking on it, stepping on it, or both. To make an exit both “click on” and “step on” activated, just include both options in the trigger attribute: trigger=“click on, step on”. By default, exits placed in the design of the VRF file will be “click on”. Exits placed on portal objects will be both “click on” and “step on”. Text specifies the text that will appear by the user's cursor, indicating that the link is active. Usually this text is the title of the page or VRF that the link leads to. But you can of course put any text here that you wish. If no text attribute is specified, then no text will appear.

Enters and exits in the <create> tag

Enters and exits can also be attached to specific objects by including them in the <create> tag. The tag syntax is the same, except that you don't need a location parameter. Remember, when you attach an exit directly to a object, then every instance of that object in your map will link to the same file. When you attach an enter to a object, and then use that object more than once in a map, then you will effectively have more than one enter with the same name. Lets say you have an enter named “doorway” attached to a object that appears three times in your map. When a visitor travels through a link to the “doorway” enter, VRGrid will chose one of the 3 doorway enters to use at random.

A note about enters

Enters can only be placed on empty spaces or on certain kinds of objects. If an enter is placed on a location that is occupied by a object with a solid shape, then VRGrid will remove the model for that object, and it won't appear in your VRF. This includes the portal object. If you want a portal to act as an enter as well as an exit, you should place the enter on the location just in front of the portal object.

Linking

We are going to make a link between My VRF Test and My Tall VRF Test, and a link between two different locations within My Tall VRF Test. First, lets put in a portal. Change Level 1 of My VRF Test to look like this:

<layer number="1">  
     ## ## ## .. @@ .. ## ## ## 
     ## .. .. .. .. .. .. .. ##
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ##  
     ## .. .. .. .. .. .. .. ##  
     ## .. .. .. .. .. .. .. ## 
     ## .. .. .. .. .. .. .. ##  
     ## ## ## ## ## ## ## ## ## 
 </layer> 

Then, add this exit tag just before the </design> tag:

<exit location="(5,1,1)" href="mytallvrf.vrf#default" trigger="click on, step on" text="tallvrf"/>
This has established a one-way link from the portal in My VRF Test, located at (5,1,1), to the default enter in My Tall VRF Test. A visitor can travel from My VRF Test to My Tall VRF Test, but not back again, because there is no <exit> tag in the My Tall VRF Test file.

Create a two-way link

In order to make this a two-way link, add this tag before the </design> tag in My Tall VRF Test:

<exit location="(5,1,1)" href="myfirstvrf.vrf#default" trigger="click on, step on" text="firstvrf" />

And put a portal in that location to mark the link:

<layer number="1"> 
     ## ## ## .. @@ .. ## ## ## 
     ## AA .. .. .. .. .. BB ## 
     ## ## .. .. .. .. .. .. ## 
     ## ## .. .. .. .. .. .. ## 
     ## KK .. .. .. .. .. .. ## 
     ## hh .. .. .. .. .. .. ## 
     ## kk .. .. .. .. @@ .. ## 
     ## DD .. .. .. .. .. CC ## 
     ## ## ## ## ## ## ## ## ## 
</layer>

Save both of your files, and open VRGrid. Go back and forth between the links. You probably noticed that when you linked back into My VRF Test, you didn't enter in the same location from which you left. This is because there is only one <enter> tag in My VRF Test, the default enter at (5,8,1). In order to create an exact two-way link between two locations, each location must have both an <enter> tag and an <exit> tag that point to each other. Also remember that the links would work just fine with or without the portal objects. The portal is just a convention to indicate that a link is present.

Create a direct two-way link

In order to create a direct two-way link, add this <enter> tag to My VRF Test:

<enter location="(5,2,1)" name="second" angle="180,0" />
And go back to the <exit> tag in My Tall VRF Test and change it to read:
<exit location="(5,1,1)" href="myfirstvrf.vrf#second" trigger="click on, step on" text="firstvrf" />
Now you have a direct link between two locations in two different vrf´s. Next, we'll add an internal link between two different locations within My Tall VRF Test.

Create a direct link.

In your My Tall VRF Test file, add these tags to the design:

<enter location="(7,6,1)" name="floor" />
<enter location="(7,6,3)" name="roof" />
<exit location="(7,7,1)" href="#roof" trigger="click on, step on" text="Up to the Roof" />
<exit location="(7,7,3)" href="#floor" trigger="click on, step on" text="Down to the Floor" />
And mark your links with portals.

Change layer 1 to the following:

<layer number="1"> 
     ## ## ## .. @@ .. ## ## ## 
     ## AA .. .. .. .. .. BB ## 
     ## ## .. .. .. .. .. .. ## 
     ## ## .. .. .. .. .. .. ## 
     ## KK .. .. .. .. .. .. ## 
     ## hh .. .. .. .. .. .. ## 
     ## kk .. .. .. .. @@ .. ## 
     ## DD .. .. .. .. .. CC ## 
     ## ## ## ## ## ## ## ## ## 
</layer>

And then add a layer 3 that looks like this:

<layer number="3"> 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. ..
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. @@ .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
</layer>

And now you will need to change your <map> tag accordingly:

<map dimensions="(9,9,3)" />

Save both of your files and open My Tall VRF Test in VRGrid. Experiment jumping around between all of the links you have created.

<vrf> 
<globals> 
<title name="My Tall VRF Test" /> 
<lib href="https://ptsource.github.io/VRGrid/libs/basic.vlib"/> 
<assets href="https://ptsource.github.io/VRGrid/assets/" />
<map dimensions="(9,9,3)" /> 
<sky texture= "images/clouds.gif" brightness="90%" /> 
<ground texture="images/dirt.gif" /> 
<atmosphere brightness="100%" /> 
<ambience file="sounds/waves.wav" volume="65%" playback="looped"/> 
<devel />
</globals> 
<design>
<create unit="AA" vrobj="basic:curvein"> 
    <param orient="east,0"/> 
</create> 
<create unit="BB" vrobj="basic:curvein"> 
    <param orient="west,0"/> 
</create> 
<create unit="CC" vrobj="basic:curvein"> 
    <param orient="north,90"/> 
</create> 
<create unit="DD" vrobj="basic:curvein"> 
    <param orient="north,270"/> 
</create> 
<create unit="##" vrobj="basic:full"> 
    <side name="n,s,e,w" texture="images/pinkmarble.gif" /> 
</create> 
<create unit="--" vrobj="basic:ceiling"> 
    <side name="bottom" texture="@basic:edgetop.gif" />
</create> 
<layer number="1"> 
     ## ## ## .. @@ .. ## ## ## 
     ## AA .. .. .. .. .. BB ## 
     ## ## .. .. .. .. .. .. ## 
     ## ## .. .. .. .. .. .. ## 
     ## KK .. .. .. .. .. .. ## 
     ## hh .. .. .. .. .. .. ## 
     ## kk .. .. .. .. @@ .. ## 
     ## DD .. .. .. .. .. CC ## 
     ## ## ## ## ## ## ## ## ## 
</layer> 
<layer number="2"> 
     ## ## ## -- -- -- ## ## ##
     ## -- -- -- -- -- -- -- ##
     ## NN -- -- -- -- -- -- ## 
     ## .. -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ##
     ## ## ## ## ## ## ## ## ##
</layer> 
<layer number="3"> 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. ..
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. @@ .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
</layer>
<enter location="(5,8,1)" name="default" angle="0.0" /> 
<exit location="(5,1,1)" href="myfirstvrf.vrf#default" trigger="click on,step on" text="first" /> 
<enter location="(7,6,1)" name="floor" /> 
<enter location="(7,6,3)" name="roof" /> 
<exit location="(7,7,1)" href="#roof" trigger="click on, step on" text="Up to the Roof"/>
<exit location="(7,7,3)" href="#floor" trigger="click on, step on" text="Down to the Floor" /> 
</design> 
</vrf> 

Adding Sound

There are four different ways that sounds can be used in vrf´s, the sound object, sounds attached to objects in the <create> tag, and sounds assigned to particular locations in the map. We've already discussed the <ambience> tag that goes in the globals of your vrf file. Your visitors will hear the ambient sound at the same volume throughout the entire vrf. The other two methods of using sound are attached to objects or locations, and therefore the sound will get louder as your visitors aproach the object or location that holds the sound. All sounds used in vrf´s must be in WAV format.

The sound object ”~“

The sound object has no 3D model. You can't see it at all you can only hear it. If you want to have a sound that appears to come from an object, then you want to use the <create> tag to add a sound to whatever object you want. If you just want a sound to emanate from a general area in a vrf, then you want to use a sound object or assign it to a particular location in your map. Even when you are using the sound object, you still need to use the <create> tag to assign the correct sound to your object, so lets look at how that works.

Using sound in the <create> tag

The tag for sound has eight attributes: file, volume, playback, delay, flood, radius, rolloff, and name. The syntax is as follows:

<create unit="xx" vrobj="sound">
<sound file="sounds/noise.wav" volume="number%"
playback="looped|random|once|single"
delay="minimum..maximum" flood="yes|no"
radius="number of objects" rolloff="1.0"
name="sound name" />
</create>

Be sure to include the path when you name the file, if your sounds aren't in the same folder as your VRF file. Volume is expressed as a whole number percentage. Playback determines how a sound will be played. There are 4 different playback options: looped, random, once, and single. Playback=“looped” will cause the sound to play continuously. If playback=“once”, the sound will play only once. If playback=“single”, then the sound will play once every time the player enters the specified radius. If playback=random”, the sound will play at random intervals. If playback=“random”, you can also specify a range of delay times between playbacks. Delay times are measured in seconds, and are measured from the time that the sound begins, rather than when it ends. For example, if your sound is five seconds long, playback=“random”, and delay=“5..10”, then sometimes the sound will play back to back, as the length of the sound file is the same as the minimum delay time, and no more than 5 seconds will ever elapse between when the sound ends and when it begins again. The maximum delay time, 10 seconds, minus the length of the sound itself, 5 seconds, leaves a maximum silence of 5 seconds. The volume of a sound will drop off gradually as you get farther away from the source. But if flood=“yes”, then the sound will play at the specified volume throughout the specified radius, rather than dropping off gradually. Radius is measured in objects, and has two different roles. On a sound with flood=“yes”, the radius defines how large an area will be filled with that sound. If volume=“100%”, flood=“yes”, and radius=“5”, then the sound will be heard at full volume right up to the edge of the 5 object border, at which point it will turn off completely. On a sound with playback=“once” or playback=“single”, the radius acts as a trigger. The sound will be played when the user enters the specified radius. Rolloff determines how quickly the sound volume will taper off as you move away from the sound source. In most cases, the default value (rolloff=“1.0”) is the most natural setting for this parameter. But if you need more control over how the sound drops off, you can change the rolloff value. If rolloff=“2.0”, then the sound will drop off twice as fast (meaning it will be audible only half as far away from the source.) If rolloff=“0.5”, then the sound will drop off half as fast (meaning it will be audible twice as far away.) The default values for these attributes are as follows: volume=“100%, playback=“looped” delay=“5..10” radius=“1” rolloff=“1.0”. Note that a object can only have one sound attached to it, unless you give each sound a name attribute.

Using Sounds in the <design> You can also assign sounds to a specific location in the map by simply adding a location parameter to the <sound> tag and placing it in the body of the VRF file (usually at the end) rather than in the <create> tag:

<sound file="sounds/noise.wav" volume="number%"
playback="looped|random" delay="minimum..maximum"
flood="yes|no" radius="number of objects"
location="(column,row,level)" />

Improving performance

Having lots of sound sources in a vrf can tax the performance of VRGrid. If you attach a sound to your floor object for instance, and that object appears 25 times in your vrf, VRGrid has to keep track of 25 different sound sources. Visitors to your vrf will get much better performance out of VRGrid if you place that sound on one location, or scatter a few sounds sources around the vrf. If you set flood=“yes”, and your radius overlap, the sound will play at a consistent volume throughout the area. Just like custom textures, sound files will be downloaded in the order in which they appear in the VRF file. Because sound files are often quite large, it is a good idea to list any <create> tags that include sounds last. On the other hand, if you want your visitors to hear a sound immediately upon entering a vrf (or at least as soon as possible) then put the tag for that sound first before the other <create> tags.

Add a sound to your vrf

In My Tall VRF Test, add the following code after the <design> tag:

<create unit="~~" vrobj="basic:sound"> 
    <sound file="sounds/giggle.wav" volume="75%" radius="5" flood="yes" playback="looped" /> 
</create> 
<create unit="cc" vrobj="basic:ceiling"> 
    <side name="top" texture="images/vrgrid.vri" style="scaled"/> 
    <side name="bottom" texture="@basic:edgetop.gif" /> 
    <sound file="sounds/guffaw.wav" volume="100%" playback="random" delay="3..6" /> 
</create>
Change layer 2 to look like this:
<layer number="2"> 
     ## ## ## -- -- -- ## ## ##
     ## cc -- -- -- -- -- cc ## 
     ## NN -- -- -- -- -- -- ## 
     ## .. -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##  
     ## -- -- -- -- -- -- -- ## 
     ## cc -- -- -- -- -- cc ## 
     ## ## ## ## ## ## ## ## ##  
</layer> 
And change layer 3 to look like this:
<layer number="3"> 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. ..
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. ~~ .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. @@ .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. ..  
</layer>

Now save it and open it in VRGrid. Go up to the roof of the vrf, move around and listen to the different ways the sounds work. You should be able to hear 3 different sounds, the constant ambient sound (unless you took this tag out), the guffaws that you hear intermittently and are louder if you are close to a image, and the giggle that plays at a constant volume throughout the area.

<vrf> 
<globals> 
<title name="My Tall VRF Test" /> 
<lib href="https://ptsource.github.io/VRGrid/libs/basic.vlib"/>
<assets href="https://ptsource.github.io/VRGrid/assets/" />
<map dimensions="(9,9,3)" /> 
<sky texture= "images/clouds.gif" brightness="90%" /> 
<ground texture="images/tiles.vri" /> 
<atmosphere brightness="100%" /> 
<ambience file="sounds/waves.wav" volume="65%" playback="looped"/> 
<devel />
</globals> 
<design>
<create unit="~~" vrobj="basic:sound"> 
    <sound file="sounds/giggle.wav" volume="75%" radius="5" flood="yes" playback="looped" /> 
</create> 
<create unit="cc" vrobj="basic:ceiling"> 
    <side name="top" texture="images/vrgrid.vri" style="scaled"/> 
    <side name="bottom" texture="@basic:edgetop.gif" /> 
    <sound file="sounds/guffaw.wav" volume="100%" playback="random" delay="3..6" /> 
</create> 
<create unit="AA" vrobj="basic:curvein"> 
    <param orient="east,0"/> 
</create> 
<create unit="BB" vrobj="basic:curvein"> 
    <param orient="west,0"/> 
</create> 
<create unit="CC" vrobj="basic:curvein"> 
    <param orient="north,90"/> 
</create> 
<create unit="DD" vrobj="basic:curvein"> 
    <param orient="270,90"/> 
</create> 
<create unit="##" vrobj="basic:full"> 
    <side name="n,s,e,w" texture="images/pinkmarble.gif" /> 
</create> 
<create unit="--" vrobj="basic:ceiling"> 
    <side name="bottom" texture="@basic:edgetop.gif" />
</create> 
<layer number="1"> 
     ## ## ## .. @@ .. ## ## ##
     ## AA .. .. .. .. .. BB ## 
     ## ## .. .. .. .. .. .. ## 
     ## ## .. .. .. .. .. .. ## 
     ## KK .. .. .. .. .. .. ## 
     ## hh .. .. .. .. .. .. ## 
     ## kk .. .. .. .. @@ .. ## 
     ## DD .. .. .. .. .. CC ## 
     ## ## ## ## ## ## ## ## ## 
</layer> 
<layer number="2"> 
     ## ## ## -- -- -- ## ## ##
     ## cc -- -- -- -- -- cc ## 
     ## NN -- -- -- -- -- -- ## 
     ## .. -- -- -- -- -- -- ## 
     ## -- -- -- -- -- -- -- ##
     ## -- -- -- -- -- -- -- ##  
     ## -- -- -- -- -- -- -- ## 
     ## cc -- -- -- -- -- cc ## 
     ## ## ## ## ## ## ## ## ##  
</layer> 
<layer number="3"> 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. ..
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. ~~ .. .. .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. @@ .. .. 
     .. .. .. .. .. .. .. .. .. 
     .. .. .. .. .. .. .. .. ..  
</layer>
<enter location="(5,8,1)" name="default" angle="0.0" />
<exit location="(5,1,1)" href="myfirstvrf.vrf#default" trigger="click on,step on" text="first" />
<enter location="(7,6,1)" name="floor" /> 
<enter location="(7,6,3)" name="roof" /> 
<exit location="(7,7,1)" href="#roof" trigger="click on, step on" text="Up to the Roof"/>
<exit location="(7,7,3)" href="#floor" trigger="click on, step on" text="Down to the Floor" />    
</design> 
</vrf> 

Lighting

We have already discussed the <atmosphere> tag, which goes in the globals section of the VRF file. Atmosphere lights everything in your vrf evenly, without creating any shadows. If you are going to be using lighting effects in your vrf, then you should set your atmosphere relatively low (around 50% or less), so that your other lights will show up more dramatically. Aside from atmosphere, there are three different categories of light, orb light, point_light, and vrf_light. Orb light is light that shines from a specific direction in the sky, illuminating the entire vrf. Point_light is light that shines in all directions from a specified location. vrf_light is light that shines in a specified direction from a specified location.

The <orb> tag

<orb texture="folder/image.gif" position="(turn,tilt)"
brightness="percentage%" color="(red,green,blue)" />

The <orb> tag allows you to place a light source in the sky that affects your entire vrf, much like the sun or moon would in the real world. When you use the <orb> tag, you also have the ability to “hang” a sun or moon texture in the sky. There is at least one default orb texture that is included in each library. In the Basic library, that texture is a bright sun. There is a full moon texture included in the Village library. And of course, you can specify a texture of your own. The <orb> tag is always placed in the globals section of the VRF file.

No matter what texture you use in the sky, light will shine from the location of the texture illuminating the entire vrf. Unlike atmosphere, light from the orb will create shadowed areas. Ambient light will illuminate all areas of a vrf, regardless of whether or not they are exposed to the sky. But orb light will only illuminate surfaces that face the light source. Position refers to where the orb will sit in the sky. Position is expressed as a pair of angles called “turn” and “tilt”. The turn angle specifies what direction the orb will be in. Possible values are from 0-359, with 0 refering to north, 90 to east, 180 to south, etc. The tilt angle defines how high in the sky the orb will appear. Possible values range from -90 to 90, with 0 being at the ground, or “horizon”, 90 being directly overhead, etc. Brightness defines how bright the orb light will be. And texture defines what image will be displayed. Brightness will be 100% by default, and the default orb texture will be displayed in the sky if no other texture is specified. Color allows you to define the color of the light.

You can also turn your orb into a hyperlink by adding an href parameter:

<orb texture="folder/image.gif" position="(turn,tilt)"
brightness="percentage%" color="(red,green,blue)" href="url"
text="text" />

Add orb light to your vrf First, you'll want to lower the atmosphere in your vrf so that your lighting effects will show up. In My Tall VRF Test, change the <atmosphere> tag in the head to read:

<atmosphere brightness="30%" />

Then place the following tag in the globals section of My Tall VRF Test:

<orb position="(45,45)" brightness="60%" />

The <point_light> tag

There are two different styles of point_light (static and pulsate).

Static point_light. The static point_light tag looks like this:

<point_light style="static" position="(x,y,z)" brightness="brightness%" radius="number_of_units"
flood="yes|no" color="(red,green,blue)" />

Here, position refers to the placement of the light within the object space. Position=”(0,0,0)“ would place the light at the bottom southwest corner of the object. position=”(128,256,128)“ would place the light in the middle of the top of the object. Lights will be placed in the center of the object (128,128,128) by default if no position is defined. Brightness defines how bright the light will be at the position of the source. Radius defines how far from the source the light will be visible. If radius=“4” and brightness=“90%”, then the light will be 90% brightness at the location of the light source, and will fade gradually to whatever the atmosphere level is 4 objects away. That is, unless flood is set to “yes”. Flood=“yes” will cause the light to flood the entire radius at the specified brightness level. In the above example, if flood were turned on, then light would appear at 90% brightness for the entire 4 object radius, and the light would drop sharply to the ambient level at the edge of the 4 object radius. The flood parameter defaults to “no”. Color allows you to define the color of the light. Note that every polygon inside of a light's radius will not necessarily be illuminated. Only those polygons that face the light will be lit. A polygon that is within the radius of a light, but is not facing it, will not be affected by the light.

Pulsating point_light. The tag for a pulsating point_light is slightly different:

<point_light style="pulsate" position="(x,y,z)" brightness="min%..max%" radius="number_of_units" 
flood="yes|no" color="(red,green,blue)"
speed="cycles_per_second" />

Notice that the brightness parameter describes a range between two values. And there is an added speed attribute. If brightness=“20%..80%” and speed=“2”, then the light level will pulse from 20% to 80% and back again twice every second. You can slow the pulse down by assigning a value less than 1 to the speed parameter. Speed=”.25“ would create a light that takes four seconds to raise to its brightest level and back again. As an example go back to the <create> tag for your cc unit in My Tall VRF Test (the “cc” unit you created), and add the following point_light:

<point_light style="pulsate" position="(128,0,128)"
brightness="20%..90%" radius="1" flood="yes"
color="(0,0,255)" speed="1" />

So the entire <create> tag for the “cc” object will look like this:

<create unit="cc" vrobj="basic:ceiling">
<part name="top" texture="images/vrgrid.vri" />
<part name="bottom" texture="images/pinkmarble.gif" />
<sound file="sounds/guffaw.wav" volume="100%"
radius="2" playback="random" />
<point_light style="pulsate" position="(128,0,128)"
brightness="20%..90%" radius="2" flood="yes"
color="(0,0,255)" speed="1" />
</create>

This will make a pulsating light under all of your “cc” objects. This point_light is assigned to the bottom of the object space. Your “cc” objects textures will not be lit by it because they face away from it. In order to light the “cc” objects textures themselves, you would want to place a light above the “cc” objects, in layer 3 of your map.

The <vrf_light> tag

There are 3 different kinds of vrf_lights (static, search, and revolve). A static vrf_light shines a still cone of light. A searching vrf_light moves back and forth between 2 specified points. A revolving vrf_light rotates in a defined circle. The tag for a static vrf_light looks like this:

<vrf_light style="static" position="(x,y,z)"
brightness="brightness%" radius="number_of_units"
flood="yes|no" color="(red,green,blue)"
direction="(turn,tilt)" cone="angle" />

Position, brightness, radius, flood, and color all work the same here as they do for point_lights. Direction describes where the vrf_light is focused, and is expressed as a pair of angles. If no direction parameter is present, the light will face exactly north and horizontal to the ground plane by default, or direction=”(0,0)“. The first angle is called the “turn”. The turn angle describes rotation in the horizontal plane. Possible values range from 0 to 359, where 0 is north, 180 is south, etc. The second angle is called the “tilt” and describes how far above or below the horizontal plane the light points. Possible values range from -90 to 90, where 0 is horizontal to the ground, 90 points straight up, and -90 points straight down. With the turn and tilt angles, you can describe any possible direction for your light to point. Cone describes how wide the vrf_light is. Cone is the diameter of the influence of the light, expressed as a degree, (0 to 359). The default value for cone is 45. So a vrf_light with direction=”(45,0)“ and cone=“90” would illuminate the northeastern corner of a scene (assuming that the vrf_light is in the center of the scene.) The turn angle is 45 pointing directly northeast, the tilt angle is 0 pointing parallel to the ground plane, and the cone is 90 which spreads the light out over a 90 degree area from the north axis to the east axis. Direction=”(0,-90)“ would create a light that points straight down.

Searching vrf_light. The tag for a searching vrf_light would look like this:

<vrf_light style="search" position="(x,y,z)"
brightness="brightness%" radius="number_of_units"
flood="yes|no" color="(red,green,blue)"
direction="(turn1,tilt1)..(turn2,tilt2)"
cone="angle" speed="cycles_per_second" />

In a search style vrf_light, you can define two different directions and the search light will move smoothly back and forth between the two directions. The path that the search light takes between the two defined directions is determined by which direction has a higher value for its turn angle. The light will always travel from the lowest turn angle value to the highest. Values for the turn angles can range from -359 to 359. To make a search light that moves between a point directly north to a point directly east, you would designate direction=”(0,0)..(90,0)“, and the light would travel clockwise from the north horizon to the east horizon. But what if you wanted a light to travel between the same 2 points, but to go the long way around, passing by the south and west horizons on the way? Then you would change the value of the eastern direction to read (-270,0). Direction=”(0,0)..(-270,0)“ would create a light that travels clockwise from the eastern horizon to the northern horizon and back again, passing through the south and west on the way. Speed determines how fast the search light will move between the two directions. Speed is expressed as cycles per second. Speed=“2” would make a light that moves from direction 1 to direction 2 and back again twice per second.

Revolving vrf_lights. To create a revolving vrf_light use the following code:

<vrf_light style="revolve" position="(x,y,z)"
brightness="brightness%" radius="number_of_units"
flood="yes|no" color="(red,green,blue)"
direction="(turn1,tilt1)..(turn2,tilt2)"
cone="angle" speed="revolutions_per_second" />

This tag is very similar to the syntax for the search light, but the light will continue in a full circle through the 2 specified directions. If the turn angle of the first direction is smaller than the second one, then the light will rotate in a clockwise direction. If the second turn angle is smaller, then the motion will be counterclockwise.

Placing lights in your vrf There are three different ways to describe light in a VRF file:

  1. Adding lights to objects using the <create> tag
  2. Assigning lights to particular locations in the map
  3. Using light objects

The tags that describe point_lights and vrf_lights can be placed in the <create> tag of any object. Remember that a light included in a <create> tag will appear in every instance of that object in the map. Note that a object can only have one light assigned to it, unless you assign a name attribute to each <point_light> or <vrf_light> tag after the first. Alternately, a light can be assigned to a specific location in your map, regardless of what object might be there. To do this, simply put your light tag in the body of your VRF file (usually near the end with your enters and exits). You will also need to add a location parameter to the light tag to place the light at a specific location in the map. The location parameter works just the way it did for sounds: location=”(column, row, layer)“ . Add a search light In My Tall VRF Test, add the following tag to the end of the body, just before your enters and exits:

<vrf_light style="search" position="(1,1,128)"
brightness="100%" radius="7" location="(4,4,1)"
direction="(17,3)..(132,3)" cone="30" speed=".5" />
This should give you a vrf_light that searches back and forth between the two portals on layer 1 of My Tall VRF Test.

Popups

Popups are 2D images or text that you can assign to specific locations in your map. They are not visible to the visitor at first, but “pop up” on the screen when the visitor gets within a defined radius of the location that holds the popup, or when she rolls her mouse over a object that holds the popup. Popups are very useful for including extra information that you want a visitor to be able to see, without cluttering up your vrf. They are great for providing detailed info about many objects in the vrf. They also can be used to provide a simple navigational map of your spot vrf is visible right at enter. The <popup> tag, like the <enter> and <exit> tags, can go anywhere in the design. Popups can also be attached to objects by putting the <popup> tag inside a <create> tag. Popups can contain either textures, text, or imagemaps. Lets start by just looking at a simple <popup> tag:

<popup location="(column,row,level)"
trigger="rollover,proximity|everywhere" radius="objects"
texture="folder/image.gif" placement="mouse|top-left|top|
top-right|left|center|right|bottom-left|bottom|bottom-right"
brightness="number%" />
Location describes where in the map the popup is anchored. If the popup is attached to a object in a <create> tag, then the location parameter is not needed. If the popup is not attached to a object, and the location parameter is left out, then the popup will be displayed throughout the entire vrf. Trigger is how the popup gets activated, either by rolling over it with the mouse, or by coming within the specified radius, or both. Or, if trigger=“everywhere”, then the popup will appear throughout the entire vrf. Radius is how close the user has to be to the location to trigger the popup (when trigger is set to “proximity”). Radius is described as a whole number of objects. Unlike lights and sounds, the radius for popups only functions on one layer, i.e. a popup on layer 4 with a radius of 2 will not be visible on layers 3 or 5. Texture defines the file that will pop up. Placement describes where on the user's screen the image will appear. When placement=“mouse”, the popup will appear in the same location as the user's cursor. Brightness defines how bright the popup will appear. You can also put text in popups by adding the following attributes to the <popup> tag:
text="message"
textalign="top-left|top|top-right|left|center|right|
bottom-left|bottom|bottom-right"
textcolor="(r,g,b)"
Textalign defines how your text will appear in relationship to the popup texture. textcolor is the color of the text. You can also assign a color to the popup itself, rather than a texture. To do so, you will need these two additional tags:
color="(r,g,b)"
size="(width,height)"
Size defines the size of the rectangle of color on which your text will appear, measured in pixels. If you place text over an image, then the color attribute will be used to define a color for a drop shadow on the text, making it easier to read against the background image. If no color is defined, then the background of the popup will be transparent by default.