Hi Terry,

I attached a working example which creates a changelist from the current
state. To skip the prototypes I added the start parameter this should be
the first FieldContainerPtr you created in your app. I will add this
method to the RemoteAspect class. This works fine for apps which use
only one aspect I'm not sure what happens with more than one aspect.

Andreas

static void createCurrentStateChangeList(const FieldContainerPtr &start,
ChangeList *cl)
{
     cl->clearAll();
     const std::vector<FieldContainerPtr> &fcs =
*FieldContainerFactory::the()->getFieldContainerStore();

     bool found_start = false;
     for(unsigned int i=0;i<fcs.size();++i)
     {
         FieldContainerPtr fc = fcs[i];
         if(fc != NullFC)
         {
             if(fc == start)
                 found_start = true;

             if(found_start)
             {
                 cl->addCreated(fc.getFieldContainerId());
                 for(UInt32 j=0;j<fc.getRefCount();++j)
                     cl->addAddRefd(fc);
                 cl->addChanged(fc, FieldBits::AllFields);
             }
         }
     }
}




What I was looking for originally was a way to artificially create a
complete change list from an existing model.  I would think that would
be a simpler way to reestablish a broken connection because you
wouldn't have to keep a record of all changes since the start of the
client.  Has this method been considered?

Yes I actually wanted the same but that's not so easy to implement so I
hacked this workaround.

Andreas


Again, I'm probably not seeing the real problem, but what makes this
difficult?  From what I gather from the OpenSG docs, a ChangeList can
contain items for create, destroy, change, addref, and subref. Couldn't we just traverse a graph and compile a ChangeList full of
create and addref items?  I haven't written much traversal code, but I
don't remember it being so bad.  I'd be willing to try writing this,
unless there's some big obstacle I haven't thought of.
- Terry


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=k&kid3432&bid#0486&dat1642
_______________________________________________
Opensg-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-users





// testDynamicClusterClient2
//
// OpenSG cluster client program where you can dynamicly connect/disconnect
// to the servers.
// It is similar to testDynamicClusterClient but this time we create from the
// current state a changelist and send this to the cluster servers.
// This variant is much easier to implement in your own app but could be
// problematic if you use more than one aspect in your app.

// To test it, run 
//   ./testClusterServer -w pipe0 &
//   ./testDynamicClusterClient2 pipe0
//
// press 'c' to connect to the servers and 'd' to disconnect. 


#include <OSGGLUT.h>
#include <OSGConfig.h>
#include <OSGSimpleGeometry.h>
#include <OSGGLUTWindow.h>
#include <OSGSimpleSceneManager.h>
#include <OSGMultiDisplayWindow.h>
#include <OSGSceneFileHandler.h>
#include <OSGRemoteAspect.h>
#include <OSGFieldContainerFactory.h>

#include <string>
#include <vector>

// Activate the OpenSG namespace
OSG_USING_NAMESPACE

// The SimpleSceneManager to manage simple applications
SimpleSceneManager          *_mgr = NULL;
GLUTWindowPtr               _client_win = NullFC;
MultiDisplayWindowPtr       _cluster_win = NullFC;
NodePtr                     _root = NullFC;
std::vector<std::string>    _pipenames;
FieldContainerPtr           _first_fc = NullFC;

// forward declaration so we can have the interesting stuff upfront
int setupGLUT( int *argc, char *argv[] );
void display(void);

// Initialize GLUT & OpenSG and set up the scene
int main(int argc, char **argv)
{
    std::cout << "start a cluster server with './testClusterServer -w pipe0'\n"
                 "press 'c' to connect to the servers.\n"
                 "press 'd' to disconnect from the servers.\n"
                 "press 'n' to delete current scene.\n"
                 "press 't' to create a torus.\n"
                 "press 'l' to load scene 'tie.wrl'.\n"
              << std::endl;
    
    // OSG init
    ChangeList::setReadWriteDefault();
    osgInit(argc,argv);

    // GLUT init
    int winid = setupGLUT(&argc, argv);

    // the connection between GLUT and OpenSG
    _client_win = GLUTWindow::create();
    // this is our first created fieldcontainer pointer we need this
    // to skip the prototypes in createCurrentStateChangeList().
    _first_fc = _client_win;
    _client_win->setId(winid);
    _client_win->init();
    _client_win->setSize(300,300);
    
    for(UInt32 i=0;i<argc-1;++i)
    {
        if(argv[i+1] != NULL)
            _pipenames.push_back(argv[i+1]);
    }

    if(_pipenames.empty())
        _pipenames.push_back("pipe0");
    
    _root = Node::create();
    beginEditCP(_root);
        _root->setCore(Group::create());
    endEditCP(_root);
    
    // create default scene
    NodePtr scene = makeTorus(.5, 2, 16, 16);
    beginEditCP(_root);
        _root->addChild(scene);
    endEditCP(_root);

    // create the SimpleSceneManager helper
    _mgr = new SimpleSceneManager;

    // tell the manager what to manage
    _mgr->setWindow(_client_win );
    _mgr->setRoot  (_root);

    // show the whole scene
    _mgr->showAll();
    
    // GLUT main loop
    glutMainLoop();

    return 0;
}

static void connectCluster(void)
{
    if(_cluster_win != NullFC)
        return;

    ViewportPtr clientvp = _client_win->getPort()[0];
    
    // create the viewports for the cluster just a simple one ...
    ViewportPtr vp = Viewport::create();
    beginEditCP(vp);
        vp->setCamera    (_mgr->getCamera());
        vp->setBackground(clientvp->getBackground());
        vp->setRoot      (clientvp->getRoot());
        vp->setSize      (0,0, 1,1);
    endEditCP(vp);

    // the connection between this client and the servers
    _cluster_win = MultiDisplayWindow::create();

    // all changes must be enclosed in beginEditCP and endEditCP
    // otherwise the changes will not be transfered over the network.
    beginEditCP(_cluster_win);

        for(UInt32 i=0;i<_pipenames.size();++i)
            _cluster_win->getServers().push_back(_pipenames[i]);
        // dummy size for navigator
        _cluster_win->setSize(300,300);
        _cluster_win->addPort(vp);

    endEditCP(_cluster_win);

    // create from the current state a changelist.
    RemoteAspect::createCurrentStateChangeList(_first_fc, 
Thread::getCurrentChangeList());

    // initialize window
    _cluster_win->init();

    // apply changelist to the servers
    _cluster_win->render((RenderAction *) _mgr->getAction());
    // clear changelist
    Thread::getCurrentChangeList()->clearAll();

    glutPostRedisplay();
}

static void disconnectCluster(void)
{
    if(_cluster_win == NullFC)
        return;

    ViewportPtr vp = _cluster_win->getPort(0);
    subRefCP(_cluster_win);
    _cluster_win = NullFC;

    if(vp != NullFC)
        subRefCP(vp);
}

//
// GLUT callback functions
//

// redraw the window
void display(void)
{
    // redraw the client window
    _mgr->redraw();

    try
    {
        if(_cluster_win != NullFC)
        {
            // redraw the server windows
            _cluster_win->render((RenderAction *) _mgr->getAction());
        }
    }
    
    catch(OSG_STDEXCEPTION_NAMESPACE::exception &e)
    {
        //printf("error: '%s'\n", e.what());
        printf("ClusterServer was killed!\n");
        ViewportPtr vp = _cluster_win->getPort(0);
        subRefCP(_cluster_win);
        _cluster_win = NullFC;

        if(vp != NullFC)
            subRefCP(vp);
    } 

    OSG::Thread::getCurrentChangeList()->clearAll();
}

// react to size changes
void reshape(int w, int h)
{
    glutPostRedisplay();
}

// react to mouse button presses
void mouse(int button, int state, int x, int y)
{
    if (state)
        _mgr->mouseButtonRelease(button, x, y);
    else
        _mgr->mouseButtonPress(button, x, y);
    glutPostRedisplay();
}

// react to mouse motions with pressed buttons
void motion(int x, int y)
{
    _mgr->mouseMove(x, y);
    glutPostRedisplay();
}

// react to keys
void keyboard(unsigned char k, int x, int y)
{
    switch(k)
    {
        case 27:    
        {
            OSG::osgExit();
            exit(0);
        }
        case 'n':
            beginEditCP(_root);
                while(_root->getNChildren() > 0)
                    _root->subChild(_root->getChild(0));
            endEditCP(_root);
            glutPostRedisplay();
        break;
        case 'l':
        {
            NodePtr scene = SceneFileHandler::the().read("tie.wrl");
            if(scene != NullFC)
            {
                beginEditCP(_root);
                    _root->addChild(scene);
                endEditCP(_root);
                _mgr->showAll();
                glutPostRedisplay();
            }
        }
        break;
        case 't':
        {
            NodePtr scene = makeTorus(.5, 2, 16, 16);
            beginEditCP(_root);
                _root->addChild(scene);
            endEditCP(_root);
            _mgr->showAll();
            glutPostRedisplay();
        }
        break;
        case 'c':
            connectCluster();
        break;
        case 'd':
            disconnectCluster();
        break;
    }
}

// setup the GLUT library which handles the windows for us
int setupGLUT(int *argc, char *argv[])
{
    glutInit(argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    
    int winid = glutCreateWindow("OpenSG");
    
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);

    return winid;
}

Reply via email to