The Source for Java Technology Collaboration


Home | Changes | Index | Search | Go

ProjectWonderlandFileSystem

DRAFT v0.3: The Wonderland File System (WFS) Architecture

1. Introduction

The following document is a design proposal for the architecture of the Wonderland File System (WFS). The WFS allows worlds in Project Wonderland to be defined as a series of hierarchically arranged XML files. A world in Wonderland consists of a hierarchical set of 3D volumes (called 'cells'). Currently, the creation of these cells, their properties, and the parent/child relationships among them are hard-coded. It is the purpose of WFS to allow developers to flexibly define worlds using a well-defined hierarchy of files (typically organized in directories on disk).

The architecture of WFS should be:

  • Extensible, so that new types of cells may be added with no changes required by the underlying software mechanism.

  • Developer friendly, so that the structure of the world may be edited and re-loaded easily.

  • Network aware, so that new world components may be obtained over the network.

2. Features of the "Wonderland File System"

The Wonderland File System will have the following features:

  • It will allow developers to create worlds easily, by creating a hiearchy of directories and disk files representing individual cells. The structure of the world can easily be re-arranged by re-arranging the hierarchy of files on disk.

  • A WFS represents a self-contained, relocatable set of cells and resources which may be incorporated into worlds.

  • A WFS will have a well-defined set of conventions which will help identify where components will reside in the file system and also help identify the version of the file system specification used.

  • A WFS may be archived into a single file and exported over the network.

  • A WFS defines a unique, location-independent namespace for some or all of the components contained within the file system.

2.1 Definitions

For the purposes of this architecture proposal, the following definitions apply:

A cell represents a 3D volume in Wonderland. It may consist of a collection of fixed, solid objects or represent moveable objects such as avatars.

A resource represents raw content such as a collection of polygons or shapes. They are typically created by a 3D visual authoring tool and stored in some file format specific to the authoring tool or as a Java 3D scene graph. Raw audio files are also considered resources.

3. High-Level Architecture

A Wonderland File System is a set of directories and files on disk arranged in a certain way and following certain naming conventions. A single WFS contains all of the cell definitions (as defined in XML files), (optionally) resources (e.g. artwork) used by these cells, and optionally a mapping of disk directories to uniquely-named URIs so that portions of the world may be available over the network. In general, the directory structure of a WFS will mimic the hierarchical relationship among cells in the world. A WFS, however, may also contain an archive of resources made available over the network and/or a collection of unrelated re-usable cells.

Figure 1 illustrates the high-level architecture of the Wonderland File System. Each machine runs a single instance of the Wonderland server, which defines a single, contiguous world with bounds from negative infinity to positive infinity along all three cartesian axes. Associated with each running instance of the Wonderland server is a 'root' WFS, whose path on the local filesystem is given by the 'worldRoot' property, defined within the WonderlandServerConfig? class and stored in the WonderlandServerConfig?.xml file. (Strictly speaking, more than one instance of the Wonderland server may run on a single machine, so long as they have unique network identies.)

Typically, an 'administrator' executes the Wonderland server and has read/write permission to the root WFS. 'Users', on the other hand, may run the Wonderland client, but also may wish to add content to the world.

wfs_architecture.png

In the most simple case, the root WFS defines the entire world -- it contains all of the cell definitions and all of the resources necessary to display those cells. In more advanced configurations, the root WFS (or any WFS for that matter) may allow portions of the world to be defined by other WFS located on the same server file system, or located on different machines entirely. Figure 1 illustrates an example usage of this advanced configuration, where a certain subset of the world is defined by another WFS, perhaps contained within a user's directory. In this way, the Wonderland administator can provision the world and assign parts of it to users. (For example, the administrator may define an office building, but provision offices to individual users. Individual users can then design their offices the way they wish.) A special type of cell (WFS Cell) links in other WFS's.

To facilitate the identification of WFS's and cells contained within them, the WFS architecture defines a URI type independent of the structure of the files on disk. The root WFS for each machine is always given as 'wfs://'. As described later in this document, WFS URI's may refer to entire WFS's or individual cells within a WFS. At this point, WFS URI's only refer to cells, not individual resources.

4. The Structure of a Wonderland File System

4.1 The Base-Level Directory

The top-level of each Wonderland File System is always a directory which follows the naming convention: '-wfs'. The location of the base level directory is defined by the 'worldRoot' property in the Wonderland server configuration file.

4.2 WFS Version

Each instance of a WFS will conform to some version of the WFS architecture specification. This version number consists of a major and minor version number and is stored in a file named 'version.xml' in the base-level WFS directory. The version.xml file may be absent -- if so, the system assumes the most recent version implemented by the server software. Wonderland guarantees both forward and backward compatibility for versions with the same major number. Specifications for the directory structure with different major version numbers give no compatibility guarantees. Compatibility guarantees also do not apply to specification versions < 1.0. It is not necessary for all WFS's referenced by a single running instance of the server to be of the same version -- a root WFS may contain references to other WFSs with different versions. The version.xml file is a Java Bean serlialization of the WFSVersion class as defined below.

public class WFSVersion { private int major; private int minor;

public WFSVersion() {} public int getMajor() { return this.major }; public void setMajor(int major) { this.major = major; } public int getMinor() { return this.minor }; public void setMinor(int minor) { this.minor = minor; } }

Note that in WFS two different types of version numbers exist: the entire WFS has a version number, while each cell definition has a version number as well. The later kind of version is described later.

4.3 Cell Files, Resources and Directories

Each cell within a WFS is represented by a single XML file and takes the format specified by JSR 57: Long-Term Presistence for Java Beans at http://jcp.org/en/jsr/detail?id=57. Each cell file name follows the convention: '-wlc.xml'. A cell may be removed from the world (perhaps temporarily) by simply renaming the file to not include the '-wlc' suffix. The attributes of a cell are defined by the cell's XML file itself, including its position in the world, expressed as coordinates with respect to its parent cell ('cell-local coordinates'). (Also, see "Issues" below)

The directory structure of the WFS follows the desired structure of the wonderland world -- the directory structure hierarchy defines the parent/child relationship among the cells in the world. A cell may have one or more child cells, each spatially contained within their parent. For a parent cell named '-wlc.xml', its child cells are placed with a directory named '-wld'. By simply removing the '-wld' suffix from the directory name, child cells may be (temporarily) unloaded from the world.

The resources (e.g. artwork) used by the cells are specified using URIs. These URIs may refer to a location on the server's local disk or may be located over the network (e.g. HTTP URI's). The administrator may control whether external artwork may be used in the WFS with the 'allowExternalResources' property in the Wonderland server configuration file. By default, this property is set to 'false'.

Figure 2a illustrates an example of the structure of a WFS. It contains a single cell, defined by the 'room-wlc.xml' file. The 'hall.xml' is a properly formatted XML file, however, since it does not follow the cell file naming convention it is ignored. The room cell has three children found in the 'room-wld' directory. They are: 'desk-wlc.xml', 'door-wlc.xml', and 'chair-wlc.xml'. The version.xml gives the version of the WFS specification in use; the aliases.xml file is described below.

wfs.png

4.4 WFS URI's

The Wonderland File System defines a new URI protocol type, 'wfs'. The 'wfs' URI type uniquely identifies parts of a WFS externally in a way that is independent of the exact structure of the WFS. A WFS itself maps URIs to files and directories contained within it, in a file named aliases.xml.

Each running instance of a Wonderland server always has one URI referring to the base of its root file system: 'wfs://:/'. All URIs referring to parts of the root WFS derive from this base URI. The ':' part of the URI is a DNS domain name. It is the Wonderland server itself which handles access requests to WFS URIs; they typically listen to a well-known port defined by the Project Darkstar infrastructure. If a Wonderland client has a cell which imports portions of worlds defined by a WFS URI located on another host, it contacts the Wonderland server on that host and requests the cells.

Each WFS may have one aliases.xml file which defines all of the URI mappings for it. The aliases.xml file is an XML serialization of the WFSAliases class, as defined below. An example aliases.xml file is also shown below, which refers to the WFS defined in Figure 2a. In this example, the WFS exports the 'room' cell' and the 'hall' cell. This allows other WFS's (in perhaps other Wonderland servers) to refer to elements of the WFS pictured in Figure 2a. Note that only cells may be exported -- at this time, exporting raw resources files from within a WFS is not supported. Also note that to export a cell, its disk file name does not need to follow the naming conventions outlined above, nor does any directory within it resides. This permits developers to construct entirely 'archival' Wonderland file systems and export some or all of its contents. This also permits 'hybrid' Wonderland file systems, with parts which are loaded into a world (i.e. follow the naming conventions) and parts that are simply exported for use in other Wonderland file systems.

public class WFSAliases {
   private Hashmap<URI, URL> aliases;

   public WFSAliases() {}
   public Hashmap<URI, URL> getAliases() { return this.aliases; }
   public void setAliases(Hashmap<URI, URL> aliases) { this.aliases = aliases; }
}

File: aliases.xml

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0" class="java.beans.XMLDecoder">
 <object class="java.util.HashMap">
  <void method="put">
   <string>building/components/room</string>
   <string>room-wlc.xml</string>
  </void>
  <void method="put">
   <string>building/components/hall</string>
   <string>hall.xml</string>
  </void>
 </object>
</java>

4.5 Resource Specification

Most often, cells require a certain set of external resources to render them -- the most salient example of a resource is a 3D scene graph (e.g. a Java 3D scene file, .j3s) stored on disk. Other examples of resources include audio files and external applications to display in the Wonderland world. Currently, the locations of these resources are hard-coded paths to local disk.

In the Wonderland File System, cells refer to the resources it needs using a URI, supporting the following protocols: file, ftp, ftps, http, and https.

If a resource URI contains a relative path, then the 'file' protocol type is assumed. Resources may be stored either within the WFS or anywhere on the server's local disk.

In the current version of the specification, for security reasons, the ftp, ftps, http, and https protocol types are only supported if they refer to the same machine upon which the WFS resides or if the 'allowExternalResources' flag is set to 'false'.

(In this version of the specification, resources may or may not be included in a WFS. In the future, resources may more formally become part of the WFS, and perhaps also exported via a WFS URI.)

4.6 WFS Archive Files

Any WFS may be packaged as a JAR, TAR, or ZIP file. The archive file must have the WFS root directory (i.e. '-wfs/') as its only top-level entry, all other top-level entries are ignored.

Wonderland File System archive files may be used in several ways:

  1. They may be 'dropped in' directly into an exiting WFS (without needed to unpack the archive file). In this instance the archive file must follow the naming convention: '-wla.', where may be 'tar', 'jar', or 'zip'. These archive files may also be additionally compressed using either gzip (in which case they have an additional '.gz' extension), or the UNIX compress format (in which case they have an additional '.Z' extension). There is no need to uncompress the archive file. The contents of the archive file are treated as if the archive is extracted into the current directory, without the root '-wfs/' directory.

  1. They may be made available as a bundle of resources and cells over the internet to be included in other Wonderland File Systems.

4.7 Requirements of WFS on Native 'Filesystems'

WFS maps the concepts of traditional file systems onto the organization of 3D worlds. In reality, WFS will most likely be stored on disk on some host, however WFS must not require features not found in all filesystems. Specifically, WFS only requires:

  1. A hiearchical set of files and directories can be defined.
  2. Files and directories can have names which include the '-wfs', '-wlc', and '-wld' suffixes and also the '.xml' extension.
  3. Files must have a 'last modification date' associated with it. (used for the live update of worlds)

4.8 'Live' Update of Wonderland Worlds

A developer may change the directory structure at any time; it is only when she/he 'pings' the Wonderland server does it attempt re-read the directory structure. Wonderland will provide a way to 'ping' the server through an administrative communication channel. The ability to 'ping' the server will be provided via the Wonderland graphical client and also as a simple command-line tool.

Wonderland fails gracefully when loading the world structure from disk. It ignores malformed cell XML files and malformed directories (and all files and directories below the malformed directory). Wonderland will provide a separate pre-verifier tool which will perform simple checks on the file system to report whether it contains any errors. It is the responsibility of the developer to maintain backup copies of the directory structure.

5. Including WFS's in a World

As mentioned throughout this document, WFS's represent self-contained bundles of cells which may be included in any Wonderland world. There are generally three different ways in which administrators/developers can include WFS's located elsewhere. In each of the three cases, the cell (and any of its children) is the basic unit imported into a world.

  1. If the WFS is part of the world existing on some other Wonderland server host.
  2. If the WFS is packaged in an archive available over the net.
  3. If the WFS is located locally in a user's home directory.

Case 1: In this instance a remote Wonderland server hosts a world, and also exports all or part of its world via WFS URIs. The remote Wonderland server may contain items which are included and positioned within its world and are also exported. For example, a chair may exist at a certain location within a remote Wonderland world. When importing the chair, the local Wonderland server may wish to override some of its attributes, for example, its origin.

Case 2: In this instance a WFS is packaged as an archive file located on the network and available, for example, via an HTTP URI. In this instance, the home Wonderland server must know the HTTP URI of the archive file and the WFS URI of the cell within the archive file to be imported. As in Case 1, the home Wonderland server may wish to override certain attributes of the imported cell.

Case 3: In this instance, an admistrator of a Wonderland world may wish to provision a space for various users: for example, an office building may be provisioned into separate offices, each controlled by users. In this case, a user may load a WFS into his/her provisioned spaced during runtime. This is illustrated in Figure 1.

6. Wonderland Cell Types

At the heart of Wonderland's ability to display virtual worlds is the different types of cells it supports. The following tables lists all of the cell types, with an asterisks (*) indicating new cell types defined by this specification.

Cell Type Description
Anchor* A cell which allows the teleportation to other Wonderland worlds
Animated A cell containing an animation of individual frames of a 3D volume
Audio A cell which plays audio and has an optional visual representation
Avatar A cell which represents a person in the world
Context Menu A cell which represents a menu for user selection
Java 3D A cell which is rendered by Java 3D code
Model Viewer A cell whose 3D object can be manipulated in the world
Shared App 2D A cell which displays a 2D X Windows application
Simple Terrain A cell which displays a 3D scene from file
Slide Show A cell which displays a sequence of images
Tile* A cell which displays a single 3D volume repeated to fill the space
WFS* A cell which represents the inclusion of a Wonderland File System
WFSUser* A cell which represents the inclusion of a user-defined Wonderland File System
WFSArchive* A cell which represents the inclusion of an archived Wonderland File System

This specification introduces three new cell types: Anchor, Tile, and WFS. The Anchor cell lets an avatar jump to other parts of the world, or to different Wonderland worlds entirely. The anchor cell type takes a URI (of type 'wfs') which defines the position to jump to. (We very well may need a cell on the receiving end of the transportation as well.)

The Tile cell allows a single 3D volume to be repeated at a regular interval over the bounds of the cell. (Similar to a desktop background image which may be tiled over the screen).

There are several different ways other WFS may be included in an existing world as defined in Section 5. The WFS, WFSUser, and WFSArchive cell types handle each of these three cases.

The WFS cell type takes a URI and attaches the cells referred by that URI into the world. The WFS cell may wish to override a certain set of the attributes defined by the included set of cells; currently, only the origin may be overridden (to be expanded for sure in the future). The URI may be a WFS URI, in which case it is located remotely, or a FILE URI in which case it is located locally. The root of all Wonderland worlds is defined by this cell type.

The WFSUser cell type takes a user id in the Wonderland server who is responsible for defining that part of the world. To associate a WFS with that WFSUser cell, the user sends a special administration message to the server, with the URI of the WFS that is to be loaded, and a flag that indicates whether that URI should permanently be associated with that WFS cell, or whether that assocation vanishes upon server reboot (or perhaps upon a certain timeout).

The WFSArchive cell type includes cells stores in an archive of a WFS. This cell takes the URI of the archive file and the WFS URI (perhaps empty) of the subset of the world defined in the archive to include. (Ideally, there should be no reason this should be a separate cell type, to be visited later for sure).

6.1 Adding New Cell Types to Wonderland

New cell types should be able to be added to Wonderland. It is beyond the scope of this specification to define this mechanism, except to say that Java class files may be included in a WFS in the future.

7. Wonderland File System Cell Implememtation

All cells are represented by a specially formatted XML file within a Wonderland File System. The Java SE XMLDecoder mechanism reads properly formatted XML files and instantiates Java Beans objects; the XMLEncoder writes properly formatted XML files from existing Java Beans objects. The XML files represent only that information necessary to create the world -- it is not meant as a mechanism to save the existing state of a world to disk. Instead, the Project Darkstar infrastructure provides the facility to save 'game' state to persistent storage automatically for all of its managed objects (of which cells are but one example in Wonderland). In the initial implementation, the hierarchy of the cells in memory will mimic the hierarchy of cells on disk; in future versions of Wonderland this may not be the case if it attempts to optimize this tree structure for spatially-optimized queries.

7.1 Software Architecture of Cell Classes and their Properties

A cell's configuration properties will be represented by a 'Properties' class named after the type of cell and conforming to the Java Beans pattern (fields with getter/setter methods and the default constructor). For example, the simple terrain cell type will have a class named SimpleTerrainCellProperties? class and contain all of the fields necessary to initialize the class in memory. The Properties classes will also mirror the class hierarchy of the cell classes themselves. The existing Cell GLO (Game Logic Object) classes will be augmented to refer to the Properties class and contain a constructor which takes the Properties class as an argument. Property fields will be removed from the existing Cell GLO's classes and instead the Properties class will be queried for configuration information. It is these Properties classes that will be read from disk using the XMLDecoder mechanism.

The Properties classes will contain the name of the corresponding Cell GLO class to instantiate when the XML file is read from disk. If no such information exists, Wonderland assumes the corresponding Cell GLO class is named after the Properties file, minus the 'Properties' suffix and with a 'GLO' suffix added instead. The name of the corresponding Cell GLO does not need to be given in the XML file: it may be hardcoded in the Properties class.

Although not currently a feature, the architecture should allow the potential for the configuration state to be written to disk by Wonderland in addition to reading in the world configuration. One example of a good use of this feature is for tools which allows the easy creation of Wonderland worlds (e.g. a Netbeans plugin which generates the WFS automatically).

(As an alternative, rather than have separate Cell GLO and Properties classes, the Cell GLO class itself may be redesigned to follow the Java Bean pattern for its configuration fields and be written/read from disk. This approach has several drawbacks. First, it requires that each Cell GLO class follows the Java Bean pattern (unless it otherwise defines a BeanInfo? class or a PersistenceDelegate?). This may expose fields publicly that are not intended to be exposed. Similarly, fields with public setting/getters may be written to XML files that are not part of the configuration state of the cell. Separating the 'live' state (stored in the Cell GLO class) from the 'configuration' state seems like good policy with few drawbacks.)

The position of a cell within the world is defined with respect to its parent, where the center of the parent's cell is (0, 0, 0). Currently, the Wonderland cells are created using world coordinates. Aside from converting the existing Wonderland demos into cell-local coordinates for initialization, little change should be required internally if Wonderland continues to represent the 3D object graph in world coordinates. When a cell is read from disk using a coordinate system with respect to its parent, the code may simply walk up the chain of its parents to translate the cell local coordinates into world coordinates.

7.2 Properties Class Hierarchy

The following code defines the Properties class architecture most of the cell types in Wonderland, excluding the Avatar and Moveable cell type. The comments within this code further describe each attribute.

To note: the CellProperties? class defines a method, validate() which gets invoked after the XML file is read from disk and before the Cell GLO class is created. This lets the Properties class make sure all of the information is correct, or fills in any missing information. For example, the SimpleTerrainProperties? class will make sure the 'cellBounds' property is correct, using the 'cellOrigin' and 'cellSize' attributes present in the XML file.

/**
 * The base property class for all cell types, including the following attributes:
 *
 * cellOrigin - a 4x4 matrix transformation representing the origin of the cell.
 * major - the major version of the cell property specification
 * minor - the minor version of the cell property specification
 */
public abstract class CellProperties {
   private Matrix4d cellOrigin;
   private int major;
   private int minor;

   public CellProperties() {}
   private abstract String getGLOClass();  /* Returns the name of the GLO class */
   private void validate() {}              /* Called before the GLO is created  */

   public Matrix4d getCellOrigin() { return this.cellOrigin; }
   public void setCellOrigin(Matrix4d cellOrigin) { this.cellOrigin = cellOrigin; }
   public int getMajor() { return this.major; }
   public void setMajor(int major) { this.major = major; }
   public int getMinor() { return this.minor; }
   public void setMinor(int minor) { this.minor = minor; }
}

/**
 * The base property class for all stationary cells, including the following attributes:
 *
 * cellBounds - the physical bounds of a cell
 * safePoint - a position within the cell where avatars can be safely moved
 */
public abstract class StationaryCellProperties extends CellProperties {
   private Bounds cellBounds;
   private Matrix4d safePoint;

   public StationaryCellProperties() {}

   public Bounds getCellBounds() { return this.cellBounds; }
   public void setCellBounds(Bounds bounds) { this.cellBounds = bounds; }
   public Matrix4d getSafePoint() { return this.safePoint; }
   public void setSafePoint(Matrix4d safePoint) { this.safePoint = safePoint; }
}

/**
 * The base property class for all 'application' like cells. This is currently left
 * empty for future expansion.
 */
public abstract class ApplicationCellProperties extends StationaryCellProperties {
  public ApplicationCellProperties() {}
}

/**
 * A cell representing an X Windows application in the world, with attributes:
 *
 * application - a URI describing the application to display
 */
public class SharedApp2DCellProperties extends ApplicationCellProperties {
   private URI application;

   public SharedApp2DCellProperties() {}
   public String getGLOClass() { return "SharedApp2DCellGLO"; }

   public URI getApplication() { return this.application; }
   public void setApplication(URI name) { this.application = name; }
}

/**
 * A rectangular cell representing a simple 3D scene, with attributes:
 *
 * size - The size of each edge of the rectangular cell.
 * model - The URI of the scene graph stored on disk (somewhere).
 */
public class SimpleTerrainCellProperties extends StationaryCellProperties {
   private float size;
   private URI model;

   public SimpleTerrainCellProperties() {}
   public String getGLOClass() { return "SimpleTerrainCellGLO"; }
   public void validate() { super.setBounds(... code here...); }

   public float getSize() { return this.size; }
   public void setSize(float size) { this.size = size; }
   public URI getModel() { return this.model; }
   public void setModel(URI model) { this.model = model; }

   @Override
   public void setBounds(Bounds bounds) { /* Do nothing */ }
}

/**
 * A cell representing an animiation of a simple 3D scene, with properties:
 *
 * model - An array of URIs of the scene graph stored on disk (somewhere).
 */
public class AnimatedCellProperties extends ApplicationCellProperties {
   private URI[] models;

   public AnimatedCellProperties() {}
   public String getGLOClass() { return "AnimatedCellGLO"; }
 
   public URI[] getModels() { return this.models; }
   public void setModels(URI[] models) { this.models = models; }
}

/**
 * A cell representing an audio source in the scene, with properties:
 *
 * treatments - An array of URIs of the 3D scene representing the audio source.
 */
public class AudioCellProperties extends AnimatedCellProperties {
   private URI[] treatments;

   public AudioCellProperties() {}
   public String getGLOClass() { return "AudioCellGLO"; }
 
   public URI[] getTreatments() { return this.models; }
   public void setTreatments(URI[] treatments) { this.treatments = treatments; }
}

/**
 * A cell drawn by code which renders to a Java 3D scene graph, with properties:
 *
 * size - The size of each edge of the rectangular cell.
 * renderer - A class which renders the scene.
 */
public class Java3DCellProperties extends StationaryCellProperties {
   private float size;
   private Class renderer;

   public Java3DCellProperties() {}
   public String getGLOClass() { return "Java3DCellGLO"; }
   public void validate() { super.setBounds(... code here...); }

   public float getSize() { return this.size; }
   public void setSize(float size) { this.size = size; }
   public Class getRenderer() { return this.renderer; }
   public void setRenderer(Class renderer) { this.renderer = renderer; }
 
   @Override
   public void setBounds(Bounds bounds) { /* Do nothing */ }
}

/**
 * A cell representing a simple 3D scene which can be manipulated by the
 * client, with properties.
 *
 * model - The URI of the scene graph stored on disk (somewhere).
 */
public class ModelViewerCellProperties extends ApplicationCellProperties {
   private URI model;

   public ModelViewerCellProperties() {}
   public String getGLOClass() { return "ModelViewerCellGLO"; }

   public URI getModel() { return this.model; }
   public void setModel(URI model) { this.model = model; }
}

/**
 * A cell representing an X Windows application displayed in the world,
 * with properties.
 *
 * application - A URI describing the location of the application
 * viewingRectangle - The area in which the avatar views the application
 * xPixelScale - The scaling of pixels along the x-axis
 * yPixelScale - The scaling of pixels along the y-axis
 */
public class SharedApp2DCellProperties extends ApplicationCellProperties {
   private URI application;
   private Matrix4d viewingRectangle;
   private float xPixelScale;
   private float yPixelScale;

   public SharedApp2DCellProperties() {}
   public String getGLOClass() { return "SharedApp2DCellGLO"; }

   public URI getApplication() { return this.application; }
   public void setApplication(URI application) { this.model = application; }
   public Matrix4d getViewingRectangle() { return this.viewingRectangle; }
   public void setViewingRectangle(Matrix4d viewingRectangle) { this.viewingRectangle = viewingRectangle; }
   public float getXPixelScale() { return this.xPixelScale; }
   public void setXPixelScale() { this.xPixelScale = xPixelScale; }
   public float getYPixelScale() { return this.yPixelScale; }
   public void setYPixelScale() { this.yPixelScale = yPixelScale; }
}

/**
 * A cell representing a series of slides, with properties.
 *
 * models - An array of URIs of the slides stored on disk.
 */
public class SlideShowCellProperties extends ApplicationCellProperties {
   private URI[] models;

   public SlideShowCellProperties() {}
   public String getGLOClass() { return "SlideShowCellGLO"; }

   public URI[] getModels() { return this.models; }
   public void setModels(URI[] model) { this.models = models; }
}

/**
 * A cell representing a tiling of a 3D scene graph, with properties:
 *
 * model - The URI of the model to tile across the cell
 */
public class TileCellProperties extends StationaryCellProperties {
   private URI model;

   public TileCellProperties() {}
   public String getGLOClass() { return "TileCellGLO"; }

   public URI getModel() { return this.model; }
   public void setModel(URI model) { this.model = model; }
}

/**
 * A cell representing an 'anchor' which lets an avatar jump to
 * another part of the world or different world entirely, with
 * attributes:
 *
 * href - The URI of the point to jump to.
 */
public class AnchorCellProperties extends StationaryCellProperties {
   private URI href;

   public AnchorCellProperties() {}
   public String getGLOClass() { return "AnchorCellGLO"; }

   public URI getHref() { return this.href; }
   public void setHref(URI href) { this.href = href; }
}

/**
 * A cell representing a world (or portion thereof) defined by a
 * Wonderland File System. The location of the WFS is given by the
 * 'uri' property and can be a disk file or located on a remote
 * Wonderland server.
 */
public class WFSCellProperties extends StationaryCellProperties {
   private URI uri;
   private Matrix4d overrideOrigin;
  
   public WFSCellProperties() {}
   public String getGLOClass() { return "WFSCellGLO"; }

   public URI getUri() { return this.uri; }
   public void setUri(URI uri) { this.uri = uri; }
   public Matrix4d getOverrideOrigin() { return this.overrideOrigin; }
   public void setOverrideOrigin(Matrix4d origin) { this.overrideOrigin = origin; }
}

/**
 * A cell representing a world (or portion thereof) defined by an
 * archived Wonderland File System. The location of the WFS is given
 * by the 'uri' property and can be a disk file or located on a remote
 * Wonderland server. The 'uri' takes the form:
 *
 * <protocol>://<machine>:<port>//<archivefile>?<name>
 *
 * for example, "http://java.net/useful_stuff.tar.gz?rooms/great_office"
 *
 * where http://java.net/useful_stuff.tar.gz locates the WFS archive and
 * rooms/greatoffice locates a cell defined by the aliases.xml file within
 * the archive.
 */
public class WFSArchiveCellProperties extends StationaryCellProperties {
   private URI uri;
   private Matrix4d overrideOrigin;
  
   public WFSCellArchiveProperties() {}
   public String getGLOClass() { return "WFSArchiveCellGLO"; }

   public URI getUri() { return this.uri; }
   public void setUri(URI uri) { this.uri = uri; }
   public Matrix4d getOverrideOrigin() { return this.overrideOrigin; }
   public void setOverrideOrigin(Matrix4d origin) { this.overrideOrigin = origin; }
}

/**
 * A cell representing a world (or portion thereof) defined by a
 * user.
 */
public class WFSUserCellProperties extends StationaryCellProperties {
   private String userId;
  
   public WFSUserCellProperties() {}
   public String getGLOClass() { return "WFSUserCellGLO"; }

   public String getUser() { return this.user; }
   public void setUser(String user) { this.user = user; }
}

7.3 Example XML File

The following is the correspond XML file representation of an instance of the SimpleTerrainCellProperties? class:

<?xml version="1.0" encoding="UTF-8"?> 
<java version="1.6.0" class="java.beans.XMLDecoder"> 
 <object class="SimpleTerrainCellProperties"> 
  <void property="cellBounds"> 
   <object class="javax.media.j3d.BoundingSphere"> 
    <void property="radius"> 
     <double>4.0</double> 
    </void> 
   </object> 
  </void> 
  <void property="cellOrigin"> 
   <object class="javax.vecmath.Matrix4d"> 
    <void property="m00"> 
     <double>1.0</double> 
    </void> 
    <void property="m03"> 
     <double>63.55871105194092</double> 
    </void> 
    <void property="m11"> 
     <double>1.0</double> 
    </void> 
    <void property="m13"> 
     <double>-1.0</double> 
    </void> 
    <void property="m22"> 
     <double>1.0</double> 
    </void> 
    <void property="m23"> 
     <double>50.0</double> 
    </void> 
    <void property="m33"> 
     <double>1.0</double> 
    </void> 
   </object> 
  </void> 
  <void property="size"> 
   <float>40.0</float> 
  </void> 
 </object> 
</java> 

This example illustrates a few issues:

  1. The BoundingSphere? class is not properly serialized to XML. It's radius property is present, but not its center (because the Point3d class does not follow the Java Bean pattern). In this case, a special PersistenceDelegate? must be defined to properly serialize the BoundingSphere? class.
  2. There is an overlap in the attributes between StationaryCellProperties? and SimpleTerrainCellProperties?. Typically, simple terrain cells are defined in terms of a center and a size, from which the bounds are created (versus, say, 2D shared app cells which specify a bounds upon creation). If the developer has the ability to specify the 'bounds' property in the XML file, this could potentially create a cell with conflicting attributes. This is solved by the validate() method on the CellProperties?() class.
  3. Although the origin of the cell is represented internally as a 4D Matrix (i.e. encoded as a translation), this may not be the best way to represent it on disk. Rather a Point3d object may be best.

8. World Loading Algorithm (Roughly)

The algorithm used by the Wonderland server to load worlds from disk is as follows:

  1. At the time of initialization, the Wonderland server traverses the entire directory structure under 'worldRoot', according to the directory and file naming conventions outlined above.
  2. It (potentially) informs all clients of an update to the structure of the world (see discussion below).
  3. For each file, it instantiates the proper Properties class.
  4. It searches a list (stored using an appropriate Collection class) for the canonical name of the current file on disk being looked at. This list contains also pairs the canonical name of the file with its last modified date, and a reference to the corresponding Cell GLO class in memory. (This list is initially empty upon boot).
  5. If the file exists in the list and the last modified date of the disk file is not newer than that found in the list, the file is ignored, and traversal of the file system continues.
  6. If the file does not exist in the list, a new corresponding Cell GLO class is created, added to the server-side cache and communicated to the client for setup. An entry in the list is created for the new file.
  7. If the file exists in the list and its last modified date is older than that found on disk, then the old Cell GLO class is removed (and thus communicated to the client) and a new Cell GLO class is created, communicated to the client for setup, and an entry added to the list.
  8. For all remaining entries in the list which are not found currently on disk, their corresponding Cell GLO classes are removed from the server, removed from the client, and removed from the list.
  9. If any newly created cell causes a collision with the position of the avatar, then move the avatar to a 'safe' location. (see discussion below)
  10. It finally (potentially) informs all clients than the update to the world is complete.

8.1 Policy for Updating Clients

When updating the structure of the Wonderland world, the server may implement one of two policies: it may inform the clients that the world is being updated, wait until it processes all remaining events from the client, and forbid the client from sending new events until the world update is complete (effectively 'freezing' the client until the update is complete). Second, it may simply update the cells in the world at the same time the client continues to interact with the world.

These two end-member policies have the following traits: a policy which 'freezes' the client may result in an unacceptable user experience. On the other hand, a policy which updates the state of the world while allowing the clients to continue to interact with it may cause a set of possibly unknown error conditions.

For each client, we can break the analysis of this issue into three considerations: if a changed cell is not visible to the avatar, if the changed cell is visible to the avatar, and if the avatar is within the changed cell. For the first two cases, there should be no issues for either of the two update policies -- for a visible cell, it may briefly disappear and re-appear.

If the avatar is currently standing in a cell which is updated (changed, removed, or added), there is a potential conflict in either of the two update policies. For example, the avatar could find itself within the bounds of a new solid object in the world. (e.g. if inside of a room, a desk is added). Since the server knows the current position of the avatar, it may simply 'move' the avatar to a 'safe' position when updating the cell. Each 'stationary' cell has a property 'safePoint' which defines the coordinates (with respect to the center of the cell) that an avatar may be moved and will not collide with any solid object in the cell. By default, the vlue of the 'safePoint' property is (0, 0, 0).

9. Issues

The architecture for the WFS has several issues, summarized here:

  1. The file system architecture does not allow cell's to be defined in terms of 'global coordinates'. One possible solution is to add a flag to CellProperties? indicating that the cell origin is in 'global coordinates'. The remaining issue is where in the WFS directory hierarchy to place global-coordinate cells. They could be placed in a special directory and make Wonderland find the proper parent.
  2. The file system architecture does not easily allow for cells with multiple parents, mostly due to the fact that a cell's position in the world is defined in relation to its single parent.
  3. Although the Java Beans persistence mechanism XML format is convenient for for the XMLDecoder mechanism, it may not be human-editable easily for those not familiar with the XML schema. This issue may be mitigated by example XML files for each cell type and perhaps IDE plugins which let you visually create a world and write out the corresponding directory structure.

10. Conclusion

This document outlined the architecture of describing Wonderland worlds as a hierarchy of files and directories on disk. Minimal changes to the existing Wonderland code is necessary, with the exception of converting to a cell-local coordinate system. The main challenge of this architecture is to properly handle circumstances where changes to the world structure conflict with the existing state of the world (e.g. the current position of the avatar). This specification hopefully leaves open the possibility to load worlds and world components from over the network.

Topic ProjectWonderlandFileSystem . { Edit | Ref-By | Printable | Diffs r3 < r2 < r1 | More }
 XML java.net RSS

Revision r3 - 18 Aug 2007 - 20:09:55 - Main.jslott
Parents: WebHome > ProjectWonderland