World Processing
How to Prepare a World
 Synopsis of Prepared Scenegraph
 Deep Matrix Protos List
 How to Add an Animated Viewpoint

Making Your World Multi-user in Deep MatrixIP9

I have tried to make Deep MatrixIP9 user friendly so anyone can "hang" a world,
however I am limited to the foibles of Instant Player itself (see Bugs and Drawbacks of Instant Player  just below)

The following should be read carefully if you want to include any of the Deep Matrix Protos like shared events, or if your world
does not work correctly as is.

Worlds can be made multi-user in two ways.
1. Non-prepared World
This is when a user adds a world to the Room list ad-hoc without any preperation which requires hand coding.
However to understand the ramifications, advantages and drawbacks of a non-prepared world, some understanding of the
underlying scene-graph reading process is required.

A. How the Java EAI Client  Reads a World
When Instant Player loads a world the first thing it looks for in the first Group Node in the top layer scene graph.
If it finds a Group Node it looks at its children, then if its children consist of instances of Deep Matrix Proto instances it processes only
those children and searches for the bind-type Background Node only with in those children. It will not do any deep scene graph search.
If the VRML code being loaded does not originate from the client_application folder, then all urls for ImageTextures, AudioClips, Anchors,
Inlines, MovieTextures must be absolute urls, otherwise Instant Player will try to load the relative urls from client_application directory
resulting in a url not found error.

If it does not find any Deep Matrix Proto instances with in the children of the first top level Group Node, the Java client will first create a
Group Node with the all-necessary Walker Proto instance by the CreateVrmlFromString call. After that it will do a top to bottom scene graph
search for any Node that would have a url field and analyze the string(s) of that url field to see if they are relative or absolute.
If it determines the string is relative, it wll replace that string with an absolute one which is based on the server-directory origin of the VRML file.
This is not always successful, as Textures Not Loading and  Sound Files Not Playing discussions below make clear.
IMPORTANT! The EAI Java client CANNOT CHANGE relative urls of  EXTERNPROTOs!
This means the url will be broken andInstant Player will not be able to fetch the EXTERNPROTO and its instances will be viewed as unknown
Nodes which may cause crashes. Therefore EXTERNPROTOs must always have absolute urls to work properly in Deep Matrix IP9!
The EAI Java client also finds the first NavigationalInfo Node it finds and takes its fields for use in the Walker Proto instance. It also binds
the first Viewpoint and Background Nodes it comes to. Needless to say, while this is a convience it is also can be quite slow and is actually
done after the world itself and user's avatar have been loaded.
Besides the slowness and possible bugs, the non-prepared method will not list Viewpoints in the Java EAI chat application! This is because
the EAI cannot read the "description" field of the Viewpoint Node, because it is not an exposedField. So only prepared worlds as described
below will list Viewpoints in the Java EAI chat application. Accessing Viewpoints is still do-able in InstantPlayer's top toolbar on the left
under the Navigation heading where Viewpoints are called "cameras".

2. Prepared World
A prepared world simply means the way the old Deep Matrix applet client handled worlds. It looked for the first Group Node in the top layer scene graph
and analyzed its children as described above in  How the Java EAI Client reads a World This of course means hand-coding is necessary, but as usual
with hand-coding efforts the result will load much faster.
One major difference between stand-alone Deep MatrixIP9 and the web-page applet predessors is that all urls with in a prepared
world MUST be absolute if the world does not originate from within the client_application directory!
Relative urls will NOT be changed!
It is assumed that if the world builder has the hand coding skills to create the Deep Matrix Proto instances and properly place their Group Node
parent, then they can change any relative urls to absolute ones!

Another major difference is that the stock ProximitySensor Node used to track the user's avatar has been replaced by an extensive Proto
called "Walker". The Walker Proto instance gives out user avatar updates at given intervals. The Walker Proto instance also contains the NavigationInfo
information, provides the scripting for "beam to" and "View My Avatar" or ghost/oobe mode, and contains the default entry Viewpoint.

All Deep Matrix Protos can be found in the "Protos.wrl" file in the client_application/documentation folder.
The code there is heavily annotated. The indepth setups for prepared worlds and use of the Deep Matrix Nodes can be learned from the included
sample worlds matrix, chess, and BlackSun.

A Brief and Sketchy Deep Matrix Prepared Scenegraph Synopsis:

#VRML V2.0 utf8
# The necessary top header for any valid VRML file.
# Underneath this should be listed the Proto declarations and bodies along with any Externprotos desired.
# For brevity and clarity sake we are leaving out the majority of the "Walker" and other DM Protos declarations and bodies.
# See the Protos.wrl for the full monties.

PROTO Walker [.....]
Group {
children [....]}
# end of Walker Proto
PROTO NetworkSFBool [.....]
Group {
Script {
# End of basic SFBool shared event Proto
PROTO CtrlTime [....]
Script {
# End of  DM lock Proto
PROTO MatrixViewpoint [ ...exposedField SFString description " " ....]
Group {
Viewpoint { position IS position, orientation IS orientation set_bind IS set_bind jump IS jump
bindTime IS bindTime fieldOfView IS fieldOfView isBound IS isBound
# A semi-complete MatrixViewpoint Node

Group {
children [
# After the Proto list the VERY FIRST Group Node found in the scenegraph is mandatory as parent for the Deep Matrix Proto instances of a prepared world.
# The mandatory Walker instance and optional Deep Matrix Proto instances are listed as children of this Group Node along with any
# desired Background and Fog Nodes.
# Since the Walker has NavigationalInfo and Viewpoints built into it those particular binding Nodes are left out.
# The default Viewpoint of a world MUST be the one used in the Walker Proto!
# Other possible Viewpoints are to be instanced using the MatrixViewpoint Proto so they will be listed in Java EAI chat client.

Walker {
size 100000 10000 10000 set_speed 3 jump FALSE vporientation 0 1 0 1.57 vpposition 33 .4 3 description "Entry"
# Our mandatory Walker that replaces the ProximitySensor. Note the fields reflecting NavigationalInfo and Viewpoint Nodes.
# Its description string will show up in the Java EAI chat client under Viewpoints as the first and default Viewpoint on loading.
See my  Technical Design Note on Instant Player's EAI

MatrixViewpoint {
position 0 80 -196 orientation 0 1 0.2 3.14  fieldOfView 0.6854 description "second_view"
# This will appear for easy access at the top of Java EAI chat client underneath the Walker's description.

DEF Nsfb1 NetworkSFBool {
tag "Nsfb1_F" localCopy FALSE echo TRUE
# The shared event instance. The "_F" suffix designates it as forever persistent storage for the server.
DEF Ct1 CtrlTime {
tag "Ct1"
# The lock instance. If the user holding the lock leaves the world, the lock will clear.

Fog { visibilityRange 400 }
Background { skyAngle [75 1.2 1.7 1.8 1.9 2.1 2.75 3.14 ]
skyColor [ 0 0 0 .1 .1 .2 .3 .2 .3 .5 .1 .2 .8 0 0 .7 .4 0 .6 .3 0 .2 .7 0 1 1 1]
# Finishing up the two standard VRML binding Nodes.

# The end of our sketchy but mandatory Group Node sample for a prepared world -the rest of the file continues below:
Group {.....}
ROUTE .....
# End of VRML file

A List of the Deep Matrix Protos with Brief Descriptions
Walker {} # Mandatory. It replaces the ProximitySensor, default NavigationalInfo, and default Viewpoint Nodes.
# It does all the controlling of the user's avatar. Does the 'Beam-to' and 'Ghost' work.
# Provides governing of the output of the user's position and orientation so the two networks
# local and global are not flooded with values.

Matrix_Gui {} # Modifies the appearance of the Java EAI chat client by providing a title and/or a clickable anchor button to launch a html file.

Matrix_Anchor {}# Instant Player does not implement js the Browser.loadURL call. This is a work-around using the open source
# BrowserLauncher classes found in BrowserLauncher2-1_3.jar residing in the client_application folder. Parameters field is not implemented yet.

Matrix_Gate {} # From the original Geometrek DeepMatrix applet. It is used to switch rooms by clicking on a TouchSensor.

MatrixReceiveChat {}# Delivers the network chat to the world.

MatrixSendChat {}# Sends canned message strings to the network.

MatrixSendLocalChat {} # Sends a canned message strings to the local users chat window only.

Matrix_Text {} # Puts a text input field on the Java GUI which allows the inputed text to be read or
# displayed in the world. Useful for controlling the world events with string commands rather than TouchSensors or
#input sensors in general.

MatrixAvatar_Name_Url {}# Delivers the user's name and avatar url strings to the world.

PrimeMover {}# A HUD that positions and rotates Back pack object. Many features beyond the blaxxun version.

NetworkSFVec3f {} # Basic Shared Event. The "pilotOnly TRUE" from the original applet version is no longer used and has been replaced by
# "Ctrl + Network" Protos described below.  This is only one sample of course. There is a "Network" for all the VRML SF and MF value fields.
# Can have "_P" (populated), "_F" (forever) and "_C" (clears events) tags for persistent storage.
# Can be used in Back Pack objects.

CtrlTime{} # Basic lock and it can be used in Back Pack objects.

CtrlRemove {} # A special lock for clearing a world of all other locks in a world by one person. Useful for gaming. It can be used in Back Pack objects.

CtrlNetworkSFVec3f {}# A Lock and Shared Event in combination. The lock is established first and the shared SFVec3f can only be sent by the user
# holding the lock. If the "_F" forever tag is used and the lock holder leaves the events will still be delivered to the world and new comers.
# Again, this is only one sample of course. There is a "CtrlNetwork" for all the VRML SF and MF value fields. It can be used in Back Pack objects.

MatrixLights {} # A very simple Proto for delivering a parting SFBool FALSE value to a world when a user departs. It is useful for turning off stuff that is still
# stuck in memory. It was originally made for Contact 4.4 because Contact had memory leaks that caused it to carry lights from one world to another,
# so my work-around was to simply turn those lights off!

MatrixWorld{} # Another simple Proto that delivers a SFBool to a world after the scenegraph has been read when the developer can be sure all the EAI
#Protos are ready.

PlaneSensorFilter {} # This Proto is a govenor for ProxmitySensors, PlaneSensors, CylinderSensors, SphereSensors
# Any Sensors that provide continous output.
# It provides the same sort of protection for the network as the 'SFBool cont TRUE' field
# of Network or CtrlNetwork Protos except it also protects the LOCAL network between Instant Player
# and Java as well!
# Running a continous stream of events over the local network would put a drag on performance!
# This Proto is instanced BETWEEN the Network or CtrlNetwork and the Sensor!
# So you ROUTE from the outputing sensor to the instance of the PlaneSensorFilter and then ROUTE
# to the Network or CtrlNetwork!
# See the 'chess.wrl' for implementation and use for the shared chess pieces movements.

Matrix_Sound {} # This Proto allows Instant Player to play mp3 files through Java.

Bugs and Drawbacks of Instant Player
It should be remembered that Instant Player is still in Beta development
These are known problems that must be taken into consideration by the developer.

1. DirectionalLights Issue
  Instant Player EAI malfunctions with worlds that have DirectionalLights that are used below the top level of a world.
  Instant Player will not have EAI issues with this:

 #VRML V2.0 utf8
  DirectionalLight {......
  Directionallight {.......

 But it WILL have EAI problems with this:

#VRML V2.0 utf8

 Group {
children [
  DirectionalLight {......
Group {
children [
Group {
children [
  Directionallight {.......
]} ]}

The EAI eventOut observers stop working. For example the user's position and orientation
are no longer read from the Walker Proto and the user's avatar will remain stuck in the dead center of the world.
So the rule of thumb is that worlds that use a DirectionalLights as child, level or choice of another Node will not work.

2. ProximitySensor Creep.
 ProximitySensor Creep is a term I invented to describe an InstantPlayer issue with ProximitySensors and landscapes/Objects
 that are either the children of mulitple Transforms or the floating decimal places in the rotation and translation fields are too large like the use of
scientific notation, which was the general output of the old "CosmoWorlds" program.
 See my InstantReality forum post here for an example, details and cure:
 Overactive ProximitySensor
Basically what happens is that when the world has the above issues a ProximitySensor will constanly output a user's position that has a
very small variation on the Z axis even though the user is not moving.
In the case of small object that is the child of stacked Transforms the creep will happen when a user's position intersects an object's bound box.
When the user moves away from the bounding box the creep will stop.
In the case of landscapes the creep will be constant no matter what.
For the small objects issue not much can be done, because backpack objects can cause the problem because they are the children of stacked Transforms,
except that I have the Java client designed not to output the creep to the network, for the
latter a world developer should try to flatten out his world as much as possible (reduce the number of stacked Transforms for geometry)
and reduce the size of floating decimal places of translation and rotation fields.
A high percentage of the time this output is the result of using WYSIWYG software.
and it should be remembered that just because the VRML code is valid, does not necessarily mean it is good VRML code.
On how reduce the number of stacked Transforms in your world read this post:

use the free Seamless3D software available here:
-or for VrmlPad this post:

with the vrmlpad-scripts available here:

VrmlPad has a publish feature that does decimal reduction throughly.

3. Textures Not Loading
This happens to some worlds when they are not prepped before hand and the EAI has to do a scene graph search
to replace relative urls with absolute ones.
The only solution at the moment is to make the texture's url absolute.

4. Sound Files Not Playing
InstantPlayer does not play the mp3 format. You can use the Matrix_Sound Proto to accomplish that.
Midi files are now supported by Instant Player's most recent version.
Wav format files must be uncompressed.

If the problem file is an uncompressed wav format, then it is another case of a failed EAI scene graph  replacement of a relative url with an absolute one.
To my knowledge this is an Apple specific bug, and not just with Instant Player, but also with the old CosmoPlayer beta, and FreeWRL too.
It seems AudioClips a VRML world will still not load even after the invalid relative url is changed to a valid absolute one.
I imagine this issue applies to Movie files as well, but again this seems to be only an Apple issue.
The only solution is to change the relative url to an absolute one.

5. User Navigation Issues
If the user has a humanoid avatar (a converted AvatarStudio2 av for instance)  in any non-gravity navigation mode such as "FLY",
then there is a likely chance that at some point their avatar will unrealistically appear sticking out of the ground if they are in the wrong place.
At the present this is something that has to be lived with and viewed in the context that the "FLY" mode is itself unrealistic
except in the comics.

How to Add an Animated Viewpoint.
Animated Viewpoints in single user worlds give a very jerky trip to the user, because the animation has to fight the gravity of the world.
If you want to have a successfull animated Viewpoint in your Deep Matrix multi-user world you'll have to use the following code
(which was taken from the Prime_City world) as a guide.

Group{ # Our top grouping Node
children [

# The mandatory Walker Proto instance DEF'd as Walk
DEF Walk Walker { size 100000 100000 100000, description  "overview",  vporientation -.009 1 -.01 -1.75, vpposition -350 74.5 -292
type ["WALK","ANY"] }

# The Viewpoint to be animated
DEF drivers_seat MatrixViewpoint {
   position 494 161 -786
   orientation -.015 .998 .06 -3.64
   fieldOfView .602
   description "drivers_seat"

# The TimeSensor that drives the Viewpoint animation. It is USE'd in the Scpt Script below.
DEF drivers_seat-TIMER TimeSensor { enabled FALSE loop TRUE cycleInterval 40 }
DEF drivers_seat-POS-INTERP PositionInterpolator {}
DEF drivers_seat-ROT-INTERP OrientationInterpolator {............}

DEF Scpt Script {
eventIn SFBool set_overview
eventIn SFBool set_driver
# isBound from 'drivers_seat' ROUTE'd to set_driver

field MFString Prev ["ANY"]
# Hold Walker's old NavigationInfo type Strings

field SFNode Walk USE Walk
# The Walker instance is USE'd as Walk

field SFNode drivers_seat_TIMER USE  drivers_seat-TIMER
# The driving TimeSensor
directOutput TRUE
url "javascript:
function set_overview(v){
if(v){Walk.type = new MFString('FlY','ANY'); }
function set_driver(v){
if(v){Prev = Walk.type;
// When 'drivers_seat' MatrixViewpoint becomes bound it saves the Walker's old NavigationInfo types into 'MFString Prev'
Walk.type = new MFString('NONE');
// And changes Walk.type to "NONE"
// This is critical for successful viewpoint animation because "WALK" creates a jerky movement because of a conflict with
// the gravity of a world.
drivers_seat_TIMER.enabled = true;
// The looped driving TimeSensor is now enabled and turned on.
else {
Walk.type = Prev;
drivers_seat_TIMER.enabled = false;
// Now the reverse is done. Walker Proto gets its original NavigationInfo type Strings back.
// The looped driving TimeSensor is disabled.

ROUTE drivers_seat.isBound TO Scpt.set_driver
ROUTE drivers_seat-TIMER.fraction_changed TO drivers_seat-POS-INTERP.set_fraction
ROUTE drivers_seat-POS-INTERP.value_changed TO drivers_seat.set_position
ROUTE drivers_seat-TIMER.fraction_changed TO drivers_seat-ROT-INTERP.set_fraction
ROUTE drivers_seat-ROT-INTERP.value_changed TO drivers_seat.set_orientation

Technical Design Note on Instant Player's EAI
Instant Player implements its EAI by communicating with its classes using local network socket.
Therefore a multi-user developer is dealing with TWO networks!
1. The client/server global network of the internet.
2. Instant Player's local Java communication network.

Both have to be respected. Just as a ProximitySensor or PlaneSensor should never be allowed to pour values carte' blanche
into the client/server network, likewise they should never be allowed to pour values into the local Java communication network.
That is why I wrote the Walker Proto -to control output to both the local and global networks.
As a matter of fact, such a Proto SHOULD have been used in the all the old EAI Java applets of VNet and Deep Matrix as well.
Rick Kimball pointed out to me that the eventOut observers are an Achille's heel of  EAI and to subject them to a stream of animation values
is asking for crashing. I submit that if such a Proto would have been implemented "back in the day", then multi-user EAI would have enjoyed more
success than it did.