The network synchronization of scenery has two targets. Firstly, for CAVE setups, the scene needs to be rendered by multiple nodes from different perspectives, and secondly, multi user volume viewing sessions using networked computers.
The networking capabilities of scenery are enabled via VM parameters. The server has to be started with -Dscenery.Server=true
and the client needs to be pointed to the server via -Dscenery.ServerAddress=tcp://127.0.0.1
The server can be pretty much any scenery scene (maybe with some adjustments, see below). For a simple client use [SlimClient].
Additional VM Parameters
For server and client
scenery.MainPort
- Port for the main channel. Default: 6040
scenery.BackchannelPort
- Port for the Backchannel. Default: 6041
[SimpleNetworkExample]
[NetworkVolumeExample]
[SlimClient]
Once the server application is started, it begins scanning and registering the scene graph for objects which implement the [Networkable] interface. By default these are all nodes connected to the root node and their attributes.
When a client requests a resync, all registered objects are serialized and sent to all connected clients. Upon receiving an object, the client checks whether it has seen one with that ID before, and if not, adds its to its scene. If the object's parent has not been synced yet, it is put in a waiting queue and added once the parent has been synced. If the object is already there, the existing object is simply updated with the values of the new object.
If the server registers a change in a registered object, it sends an update with the new object to all clients.
Relevant Classes
[Networkable]
[NodePublisher]
[NodeSubscriber]
The [SlimClient] is a scenery application that offers a mostly bare scene into which scenes from a server might be loaded. In addition to that it offers its own camera if desired. If the VM parameter -Dscenery.RemoteCamera=true
is set, cameras from the server scene are disregarded and a local one is used. If it is not set or set to false, the server scene has to provide a camera.
Camera
[Camera.wantsSync] - allows disabling the registration of the camera for syncing. Default: true
Material
[DefaultMaterial.syncronizeTextures] - if set to true tries to transmit the textures over the network. Should be disabled for large textures. Default: True
Volume
[Volume.forNetwork] - Volume creation method for networkable volumes. For more see section below.
There are two ways to add objects for the client. The default way is to take the deserialized object from the server and simply add it to its corresponding parent. This works for most cases. But some objects require the constructor be run locally or with specific parameters. For those cases there are the getConstructorParameters()
and constructWithParameters(parameters)
functions in the Networkable
interface. No matter how the object was created, afterwards the update method is called again with the same object from the server. The update happens after the object has been added to the scene graph.
Example
[PointLight]
Every Networkable
object needs to implement the update
method. In the update
method a fresh copy from the server is given as parameter and should be used to copy over relevant values to the client-side object.
Properties which are marked @Transient
are not serialized and therefore not available on the client-side copy of a object from the server. If those properties need to be synced anyway, they should be returned in a serializable form in an overwrite of the getAdditionalUpdateData()
method. This method is called on the server at the serialization and the results are transmitted next to the object. The transmitted result of the getAdditionalUpdateData()
function is another parameter of the update function. Special attention has to be paid to parent classes which might also have additional data. These data have to be handled manually in the overriding methods.
References to other Networkable
objects besides parent/child relations of the scene graph and node/attribute relations can't be synced automatically. For those the Networkable.networkID
needs to be saved as additional data on the server side and resolved in the update
method with the getNetworkable
lambda parameter.
Attention: The first Update
If the object was not created with a local constructor but with deserialization, the first update will be "with itself". This might be a source of sneaky bugs when for example lists which were cleared on the "client" object are now also empty on the "server" object.
Examples
[DefaultMaterial] - AdditionalUpdateData [DefaultSpatial] - GetNetworkable, First Update
For the server to register a change, the modifiedAt
property needs to be updated. For convenience the updateModifiedAt
method simply may be called like in [DefaultSpatial].
It might be needed to prevent the server from registering an object. If wantsSync
returns false, the object will be skipped in the registration as in [Camera].
For the server to register objects out of the scene graph, they need to be returned by getSubcomponents
. The registration of attributes is handled that way for [DefaultNode]. One could extend this for rarely changing data objects to reduce the amount of times they are transmitted.
At the time of writing, serializing lambdas is wonky. Don't expect it to work. An alternative is to newly generate them on the client side in the constructWithParameters
or update
method.
Syncing volume data is currently not possible. Therefore the data has to be available locally.
To initialize a volume node with sync support, the Volume.forNetwork
create method should be used. It takes an implementation of the [VolumeInitalizer] interface.
There are already two implementations in this repo. The first is part of scenery itself [VolumeFileSource].
VolumeFileSource
has two parameters with each two options:
path
Given(val filePath: String)
- for fixed file paths that are the same on every machine (eg. network drive or something like "C://Volume")
Settings(val settingsName: String = "VolumeFile")
- the file path is taken from the VM parameter "-DVolumeFile=$path$" of each individual application
Resource(val path:String)
- the volume is a resource reachable by the java loader
type
TIFF
- tiff file format
SPIM
- Spim xml data format
The other implementation is [IJVolumeInitializer], which can be found in the [NetworkVolumeExample]. It takes a path/url and opens it using the ImageJ framework.
Examples
[NetworkVolumeExample]