My favorites | Sign in
Project Home Downloads Wiki Issues Source
READ-ONLY: This project has been archived. For more information see this post.
Search
for
NotesOnArchitecture  
Some thoughts on architecture of the viewer
Updated May 19, 2008 by nlin.mes...@gmail.com

Introduction

These are some thoughts on the architecture based on discussions with the developers and based on the Wishlist. As the wishlist encompasses a lot of functionality and represents a long-term view, so does this page on architectural thoughts. I think that to achieve everything desired on the wishlist we could use the sort of architecture described below. However we will probably need to trim the scope for the early versions of the viewer.

These are just preliminary thoughts for now. See Concerns below for some questions to consider about whether this design is good or not.

Motivation

Similar ideas can be seen in:

  • Quote: "The console is one of the most powerful features of Nebula. It's like working in a conventional console ('bash' for instance), but instead of inspecting and manipulating files one will inspect and manipulate living C++ objects directly by invoking script commands on them."
  • Verse http://verse.blender.org/ Quote: "Verse is a network protocol that lets multiple applications act together as one large application by sharing data over a network. If one application makes a change to shared data, the change is distributed instantly to all the other interested clients. The protocol and associated data format are both heavily optimized for sharing data suitable for 3D graphics. "
  • OGRE live-data plugin (forgot the URL, looking for it), a 3D content creation tool that pushes data to OGRE in a "live" fashion (as changes are being made in the tool) to allow live preview.

The main common idea is:

  • Central application "server"
    • The central viewing/rendering application, which can be thought of as a server, can be controlled at run-time by script commands (essentially messages).
  • Network transparency
    • These script commands/messages can come from within the same process or over the network.
  • Untyped messages (dynamic interface)
    • These script commands/messages coming into the server are non-type-checked. They are interpreted at runtime by the server's script interpreter. This means the interface is completely dynamic and is not fixed at compile time. This is different than a plugin interface with rigidly defined interfaces and allows for future flexibility.

The Nebula device uses its own scripting system server to handle incoming script messages. If we choose Python as our implementation language, we can use the existing Python interpreter to execute incoming strings. For instance:

    incomingMessage = "print 3+3"
    exec(incomingMessage)

With exec(), the incoming message is interpreted as Python commands and is executed. Importantly, the executed commands are completely unrestricted (any valid Python code can be sent to the server, allowing future extensibility as more server functionality is exposed) and have full access to the other variables and data structures in the hosting server program.

So any external client program can, through messages, manipulate the server's data structures.

The external client program, however, may wish to manipulate remote objects not as strings but as if they were local objects. A distributed objects library like Pyro can (hopefully) make this transparent.

Details

I'm thinking that the main framework would expose a series of abstract interfaces to internal framework objects (like WorldRenderer, ProtocolHandler). The objects can be swapped out as desired (e.g. different renderers).

Also the objects that the framework exposes could be distributed across different processes or even different machines by using a remote objects protocol. For instance, you could have two simultaneous renderers running on the same login session, to compare two different renderers in real-time. Or you could have a "debugging" renderer that just outputs the render events. This also allows something like a "debugging console" that connects to a live session (by grabbing a handle to the remote objects exposed by the framework) and has direct access to the objects being rendered.

For a distributed objects solution, I'm looking at Pyro, which seems to be proven in practice and almost transparent to use. I haven't used Pyro before so this is just early research at this point. This does have the side effect of tying us to Python. http://pyro.sourceforge.net/ An alternative is to write our own distributed objects protocol, which would be usable with any language, but would require manual require marshalling/unmarshalling of objects and method parameters as they are being passed across the wire. This manual marshalling/unmarshalling is likely unwieldy in practice and would hinder rapid development. Another alternative would be to use a full-blown remote objects framework like CORBA, which allows cross-language distributed objects, but I think this is really overkill.

The framework would not contain a "main loop"; it would contain a series of useful objects that can be tied together easily inside of an external application's main loop. These objects could then be called as needed. This is like the unix philosophy: a lot of small tools that can be combined as needed to form a solution. In particular, I think that a typical program structure for an event-based GUI is that the GUI application controls the "main loop" which waits for GUI events and responds to them. I am envisioning that inside of this main loop we call the framework objects.

An example of a GUI application could be:

 Framework = SomehowCreateRemoteFrameworkObject()

 OgreRenderer = Framework.OgreRendererFactory.Create()
 while(still running)
      GetGuiEvents()
      HandleGuiEvents()
      Framework.VirtualWorldProtocolHandler.GetandHandleEvents() // This can be an object in a different process or machine
      OgreRenderer.Render(Framework.SceneData())

While this is running we should be able to launch a second Python program with a different renderer. As an example, this application has no GUI code, just rendering.

 Framework = SomehowGetHandleToPreviouslyCreatedFrameworkObject(URL)
 IrrlichtRenderer = Framework.IrrlichtRendererFactory.Create()
 while(still running)
      Framework.VirtualWorldProtocolHandler.GetandHandleEvents()
      IrrlichtRenderer.Render(Framework.SceneData()) // same scene as Ogre renderer in real time

Or, if we want, we can just inspect the live object data for debugging:

 Framework = SomehowGetHandleToPreviouslyCreatedFrameworkObject(URL)
 print Framework.SceneData()

External world-building / world-modifying tools, which are packaged as separate standalone Python programs, could similarly just connect up to the framework in real-time, and manipulate the same live Framework objects.

The above code doesn't track publishers/subscribers explicitly; this may be needed (need to think more).

Concerns

Too complicated? Too general?

The above design is written from the point of view of a "game server" exposing its live internal objects via a scripting interface, and also that scripting interface being accessible over the network. However here, in this document, we're talking about writing a viewer, not a complete game engine. Therefore, does the existing simulator/viewer separation into server/client already provide a lot of this functionality? E.g. OpenSim exposes its world state to clients, any number of viewer (clients) can connect to the server.

At a high-level view, from an MVC perspective the MVC-Model in all its raw complexity is provided by OpenSim and is interfaced to with libsecondlife. The MVC-Viewer and MVC-controller are this viewer project.

At a lower-level view, should we have another MVC within the high-level MVC? In other words, can the viewer itself expose a simpler model (simpler than the raw libsecondlife complexity), which is interfaced to by viewers (e.g. Irrlicht, OGRE)? If the answer is yes, we should have another MVC within the high-level MVC, then the same question applies as before: should this inner MVC-Model expose its model to be accessible via a scripting language? And should that scripting language interface also then be accessible over the network?

Alternatives

  • Cross-platform plugins
  • ...
Comment by nlin.mes...@gmail.com, May 16, 2008

Notes to self: How much of the scene data needs to be marshalled/unmarshalled? I imagine Irrlicht and Ogre will have different internal scene representations. Where is scene data stored? When is it updated? We must avoid marshalling/unmarshalling huge amounts of data.

Comment by nlin.mes...@gmail.com, May 16, 2008

How to handle both cases of in-game GUI vs out-of-game GUI?

Powered by Google Project Hosting