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 {
children
Script {
}
}
}
# End of basic SFBool shared event Proto
PROTO CtrlTime [....]
{
Script {
}
}
}
# End of DM lock Proto
PROTO MatrixViewpoint [ ...exposedField SFString description " " ....]
{
Group {
children
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.
# IMPORTANT HINT: If you use Matrix_Sound and want your audio clip
to play when the user enters the room
# (assuming the viewpoint has fallen into the maxFront and maxBack
parameter range) you MUST instance the Matrix_Sound Proto
# above the Walker instance in the scene graph:
# Wrong: Group {
#
children [
#
Walker { }
#
Matrix_Sound { }
#
]}
# Right: Group {
#
children [
#
Matrix_Sound { }
#
Walker { }
#
]}
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:
http://www.web3d.org/x3d/publiclists/vrml_list_archives/0903/msg00028.html
use the free Seamless3D software available here: http://www.seamless3d.org
-or for VrmlPad this post:
http://www.web3d.org/pipermail/www-vrml_web3d.org/2009-April/000003.html
with the vrmlpad-scripts available here:
http://www.sevenemeraldtablets.net/vrmlpadscripts/vrmlpad-scripts.zip
VrmlPad has a publish feature that does decimal reduction throughly.
3. Textures Not Loading
Again, hopefully this has been fixed as of version 1.03!
What is below applies to earlier versions:
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.