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.