Hi,

On Mon, 2011-12-12 at 16:45 +0800, Gerrit Voß wrote:
> Hi,
> 
> On Thu, 2011-12-08 at 10:47 +0100, "Christoph Fünfzig" wrote:
> > Hi all,
> > 
> > >
> > Attached is an example program using two windows:
> > a GLUT window and a WIN32 window (created with WIN32 API directly; sorry 
> > Windows only ;) ).
> > The only place where aspects are assigned is the thread start
> >     thread->runFunction(::ThreadProc, // thread function
> >             1,            // aspect id
> >             NULL);        // thread argument
> > 
> > I am totally unsure if it is correct like that? I would really appreciate 
> > if someone
> > who used it before could have a look ..
> 
> I'm looking into it, from a first look (windows version still building),
> I saw a two main things
> 
> you do not apply the changes from the app aspect to aspect 1 and your
> window in the second thread still uses the aspect 0 tree.
> 
> I'll try to update you example so that the main steps are in there.

ok, attached a basic version that renders with the two windows. The main
change is syncing from aspect 0 to aspect 1 between barriers and the
use of the aspect 1 pointer for the second window.

kind regards
  gerrit


#include "OSGGLUT.h"
#include "OSGConfig.h"
#include "OSGSimpleGeometry.h"
#include "OSGGLUTWindow.h"
#include "OSGSimpleSceneManager.h"
#include "OSGSceneFileHandler.h"

#include <OSGImageFileHandler.h>
#include <OSGMatrixUtility.h>
#include <OSGNameAttachment.h>
#include <OSGSceneFileHandler.h>
#include <OSGShaderProgram.h>
#include <OSGShaderProgramChunk.h>
#include <OSGSimpleGeometry.h>
#include <OSGSimpleSceneManager.h>
#include <OSGSkinnedGeometry.h>
#include <OSGSkyBackground.h>
#include <OSGTextureObjChunk.h>
#include <OSGNavigationManager.h>

#include "OSGDrawable.h"
#include "OSGSimpleStatisticsForeground.h"
#include "OSGStatElemTypes.h"
#include "OSGStatCollector.h"
#include "OSGRenderAction.h"
#include "OSGTextureObjChunk.h"
#include "OSGMaterialChunk.h"
#include "OSGSimpleSHLChunk.h"
#include "OSGSolidBackground.h"
#include "OSGPerspectiveCamera.h"
#include "OSGProjectionCameraDecorator.h"
#include "OSGSimpleGeometry.h"

OSG::Real32 skySize = 5.0f;
unsigned win_width = 500;
unsigned win_height = 500;

OSG::SimpleSceneManager*   mgr  = NULL;
OSG::RenderAction*         ract = NULL;

bool show = true;
bool bGLFinish = false;

// WIN32 data for win2
HDC	     hDC;		// Private GDI Device Context
HWND	     hWnd;		// Holds Our Window Handle
HGLRC        hRC;
HINSTANCE    hInstance;	        // Holds The Instance Of The Application

// windows
unsigned winId = 0;
OSG::GLUTWindowRecPtr    win;
OSG::WIN32WindowUnrecPtr win2;

OSG::Thread       *pAppThread   = NULL;
OSG::ThreadRefPtr  pDrawThread  = NULL;
OSG::BarrierRefPtr pSyncBarrier = NULL;

// GLUT redraw the window
void display(void)
{
   OSG::commitChanges();

   pSyncBarrier->enter(2);
   pSyncBarrier->enter(2);

   OSG::Thread::getCurrent()->getChangeList()->clear();

   //glutSetWindow(winId);
   mgr->redraw();
}

// GLUT react to size changes
void reshape(int w, int h)
{
    glViewport(0, 0, w, h);

    mgr->resize(w,h);
    //glutPostRedisplay();
}

// GLUT 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();
}

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

// GLUT react to keys
void keyboard(unsigned char k, int, int)
{
    switch(k) {
        case 27:
        {
            delete mgr;

            win   = NULL;

            OSG::osgExit();
            exit(0);
        }

        // Output help about the controls
        // - If you add an option, please add it here too.
       case '?':
       case '/':
       case 'h':
       {
          std::cerr << "\nControls:"
                    << "v: Toggle drawing of volumes.\n"
                    << "z: Toggle zwrite on rendering action.\n"
                    << "r: switch to render action.\n"
                    << "t: switch to traversal action.\n"
                    << "n: toggle state sorting on action.\n"
                    << "m: set keygen to 0.\n"
                    << "s: set keygen for shaders.\n"
                    << "g: toggle using gl finish.\n"
                    << "x: toggle stat mode.\n"
                    << std::endl;
       }
       break;

        case 'v':
        {
            mgr->getRenderAction()->setVolumeDrawing(
                !mgr->getRenderAction()->getVolumeDrawing());
            std::cerr << "Volume Drawing: "
                      << (mgr->getRenderAction()->getVolumeDrawing() ?
                          "on":"off")
                      << std::endl;
        }
        break;

        case 'm':
            ract->setKeyGen(0);
            break;

        case 's':
        {
            OSG::UInt32 uiSId = 
                OSG::SimpleSHLChunk  ::getStaticClassId() & 0x000003FF;
            OSG::UInt32 uiTId = 
                OSG::TextureBaseChunk::getStaticClassId() & 0x000003FF;
            OSG::UInt32 uiMId = 
                OSG::MaterialChunk   ::getStaticClassId() & 0x000003FF;


            OSG::UInt32 uiKeyGen = (uiSId) | (uiTId << 10) | (uiMId << 20);

            ract->setKeyGen(uiKeyGen);
        }
        break;

        case 'g':
            bGLFinish = !bGLFinish;
            ract->setUseGLFinish(bGLFinish);
            //act->setUseGLFinish(bGLFinish);
            std::cerr << "Set use gl finish to: " << bGLFinish << std::endl;
            break;
    }
}

// change the geometry created with makePlaneGeo into quad with center origin in plane given by (dirx, diry)
// edge length is 2*size
void changePlaneGeo (OSG::GeometryUnrecPtr geo,
		     OSG::Real32 size, 
		     OSG::Pnt3f origin,
		     OSG::Vec3f dirx,
		     OSG::Vec3f diry) 
{
  //geo->removeFromProperties (OSG::Geometry::PositionsIndex);
  //geo->removeFromProperties (OSG::Geometry::NormalsIndex);

    OSG::GeoPnt3fPropertyUnrecPtr  pnts  = OSG::GeoPnt3fProperty ::create();
    OSG::GeoVec3fPropertyUnrecPtr  norms = OSG::GeoVec3fProperty ::create();
    geo->setPositions(pnts);
    geo->setNormals  (norms);

    OSG::GeoPnt3fProperty::StoredFieldType *p  = pnts ->editFieldPtr();
    OSG::GeoVec3fProperty::StoredFieldType *n  = norms->editFieldPtr();

    p->push_back(origin - size*dirx - size*diry);
    p->push_back(origin - size*dirx + size*diry);
    p->push_back(origin + size*dirx - size*diry);
    p->push_back(origin + size*dirx + size*diry);
    OSG::Vec3f normal = dirx.cross(diry);
    n->push_back(normal);
    n->push_back(normal);
    n->push_back(normal);
    n->push_back(normal);
}

// load sky-box imitation; uses skyFront.jpg/skyBack.jpg/skyLeft.jpg/skyRight.jpg/skyTop.jpg/skyBottom.jpg
OSG::NodeUnrecPtr loadBackground (void)
{
    OSG::ImageUnrecPtr           imgFront  = OSG::ImageFileHandler::the()->read("skyFront.jpg");
    OSG::TextureObjChunkUnrecPtr texFront  = OSG::TextureObjChunk::create();
    texFront->setImage(imgFront);

    OSG::ImageUnrecPtr           imgBack   = OSG::ImageFileHandler::the()->read("skyBack.jpg");
    OSG::TextureObjChunkUnrecPtr texBack   = OSG::TextureObjChunk::create();
    texBack->setImage(imgBack);

    OSG::ImageUnrecPtr           imgLeft   = OSG::ImageFileHandler::the()->read("skyLeft.jpg");
    OSG::TextureObjChunkUnrecPtr texLeft   = OSG::TextureObjChunk::create();
    texLeft->setImage(imgLeft);

    OSG::ImageUnrecPtr           imgRight  = OSG::ImageFileHandler::the()->read("skyRight.jpg");
    OSG::TextureObjChunkUnrecPtr texRight  = OSG::TextureObjChunk::create();
    texRight->setImage(imgRight);

    OSG::ImageUnrecPtr           imgTop    = OSG::ImageFileHandler::the()->read("skyTop.jpg");
    OSG::TextureObjChunkUnrecPtr texTop    = OSG::TextureObjChunk::create();
    texTop->setImage(imgTop);

    OSG::ImageUnrecPtr           imgBottom = OSG::ImageFileHandler::the()->read("skyBottom.jpg");
    OSG::TextureObjChunkUnrecPtr texBottom = OSG::TextureObjChunk::create();
    texBottom->setImage(imgBottom);

    // create box geometry
    //OSG::GroupUnrecPtr sky = OSG::makeCoredNode<OSG::Group>();
    OSG::GeometryUnrecPtr left =  OSG::makePlaneGeo(2.0f*skySize,
					      2.0f*skySize,
					      1, 1);
    OSG::GeometryUnrecPtr right =  OSG::makePlaneGeo(2.0f*skySize,
					      2.0f*skySize,
					      1, 1);
    OSG::GeometryUnrecPtr front =  OSG::makePlaneGeo(2.0f*skySize,
					       2.0f*skySize,
					       1, 1);
    OSG::GeometryUnrecPtr back =  OSG::makePlaneGeo(2.0f*skySize,
					      2.0f*skySize,
					      1, 1);
    OSG::GeometryUnrecPtr top =  OSG::makePlaneGeo(2.0f*skySize,
					     2.0f*skySize,
					     1, 1);
    OSG::GeometryUnrecPtr bottom =  OSG::makePlaneGeo(2.0f*skySize,
						2.0f*skySize,
						1, 1);
    changePlaneGeo(left, skySize, 
		   OSG::Pnt3f(+skySize, 0.0f, 0.0f),
		   OSG::Vec3f(0.0f, -1.0f, 0.0f), OSG::Vec3f(0.0f, 0.0f, 1.0f));
    changePlaneGeo(right, skySize, 
		   OSG::Pnt3f(-skySize, 0.0f, 0.0f),
		   OSG::Vec3f(0.0f, 1.0f, 0.0f), OSG::Vec3f(0.0f, 0.0f, 1.0f));
    changePlaneGeo(front, skySize, 
		   OSG::Pnt3f(0.0f, +skySize, 0.0f),
		   OSG::Vec3f(1.0f, 0.0f, 0.0f), OSG::Vec3f(0.0f, 0.0f, 1.0f));
    changePlaneGeo(back, skySize, 
		   OSG::Pnt3f(0.0f, -skySize, 0.0f),
		   OSG::Vec3f(-1.0f, 0.0f, 0.0f), OSG::Vec3f(0.0f, 0.0f, 1.0f));
    changePlaneGeo(top, skySize, 
		   OSG::Pnt3f(0.0f, 0.0f, +skySize),
		   OSG::Vec3f( 1.0f, 0.0f, 0.0f), OSG::Vec3f(0.0f, -1.0f, 0.0f));
    changePlaneGeo(bottom, skySize, 
		   OSG::Pnt3f(0.0f, 0.0f, -skySize),
		   OSG::Vec3f(-1.0f, 0.0f, 0.0f), OSG::Vec3f(0.0f, -1.0f, 0.0f));

    OSG::FieldContainerUnrecPtr mat = OSG::getDefaultMaterial()->shallowCopy();
    OSG::ChunkMaterial*   leftChunk = dynamic_cast<OSG::ChunkMaterial*>(mat.get());
    left->setMaterial(leftChunk);
    leftChunk->addChunk(texLeft);
    mat = OSG::getDefaultMaterial()->shallowCopy();
    OSG::ChunkMaterial* rightChunk  = dynamic_cast<OSG::ChunkMaterial*>(mat.get());
    right->setMaterial(rightChunk);
    rightChunk->addChunk(texRight);
    mat = OSG::getDefaultMaterial()->shallowCopy();
    OSG::ChunkMaterial* frontChunk  = dynamic_cast<OSG::ChunkMaterial*>(mat.get());
    front->setMaterial(frontChunk);
    frontChunk->addChunk(texFront);
    mat = OSG::getDefaultMaterial()->shallowCopy();
    OSG::ChunkMaterial* backChunk   = dynamic_cast<OSG::ChunkMaterial*>(mat.get());
    back->setMaterial(backChunk);
    backChunk->addChunk(texBack);
    mat = OSG::getDefaultMaterial()->shallowCopy();
    OSG::ChunkMaterial* topChunk    = dynamic_cast<OSG::ChunkMaterial*>(mat.get());
    top->setMaterial(topChunk);
    topChunk->addChunk(texTop);
    mat = OSG::getDefaultMaterial()->shallowCopy();
    OSG::ChunkMaterial* bottomChunk = dynamic_cast<OSG::ChunkMaterial*>(mat.get());
    bottom->setMaterial(bottomChunk);
    bottomChunk->addChunk(texBottom);

    OSG::NodeUnrecPtr sky = OSG::makeCoredNode<OSG::Group>();
    sky->addChild(makeNodeFor(left));
    sky->addChild(makeNodeFor(right));
    sky->addChild(makeNodeFor(front));
    sky->addChild(makeNodeFor(back));
    sky->addChild(makeNodeFor(top));
    sky->addChild(makeNodeFor(bottom));

    return sky;
}

void makeCurrent (int w)
{
   if (w < 0) {
      wglMakeCurrent(NULL, NULL);
      return;
   } 
   // make window w>0 current
   if (!wglMakeCurrent(hDC, hRC)) {
      FWARNING(("TiledSupport::makeCurrent: Can't Activate GL Context for window!\n"));
   }
   //FWARNING(("current DC=%p, current RC=%p\n", wglGetCurrentDC(), wglGetCurrentContext()));
}
void swapBuffers (int w)
{
   if (w < 0) {
      return;
   }
   if (!SwapBuffers(hDC)) {
      FWARNING(("TiledSupport::swapBuffers: Can't swap buffers for window!\n"));
   }
}
void killGLWindow (int w)
{
   FWARNING(("TiledSupport::killGLWindow\n"));
   if (!wglMakeCurrent(NULL,NULL)) {					// Are We Able To Release The DC And RC Contexts?
     FWARNING(("TiledSupport::killGLWindow: Release Of DC And RC Failed!\n"));
   }
   if (hRC) {											// Do We Have A Rendering Context?
      if (!wglDeleteContext(hRC)) {						// Are We Able To Delete The RC?
	FWARNING(("TiledSupport::killGLWindow: Release Rendering Context Failed!\n"));
      }
      hRC = NULL;										// Set RC To NULL
   }

   if (hDC) {
      if (!ReleaseDC(hWnd, hDC)) {					// Are We Able To Release The DC
	FWARNING(("TiledSupport::killGLWindow: Release Device Context Failed!\n"));
      }
      hDC = NULL;								// Set DC To NULL
   }

   if (hWnd) { 
      if (!DestroyWindow(hWnd)) {					// Are We Able To Destroy The Window?
	FWARNING(("TiledSupport::killGLWindow: Could Not Release hWnd!"));
      }
      hWnd = NULL;							// Set hWnd To NULL
   }
}

// function executed within the thread
void ThreadProc (void* )
{
   std::cout << "enter ThreadProc" << std::endl;

   pSyncBarrier->enter(2);

   pAppThread->getChangeList()->applyNoClear();

   pSyncBarrier->enter(2);

   OSG::commitChanges();

   OSG::WIN32Window *pLocalWin = 
       OSG::convertToCurrentAspect<OSG::WIN32Window *>(win2.get());

   makeCurrent(0);

   while (true) {
       pSyncBarrier->enter(2);

       pAppThread->getChangeList()->applyNoClear();

       pSyncBarrier->enter(2);

       OSG::commitChanges();

       pLocalWin->render(ract);
//     swapBuffers(0);
   }
}

// create OpenGL window
bool createWindow ()
{
   if (hInstance == NULL) { // register window class
     hInstance	    = GetModuleHandle(NULL);			// Grab An Instance For Our Window
     WNDCLASS  wc;						// Windows Class Structure
     wc.style	    = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	// Redraw On Size, And Own DC For Window.
     wc.lpfnWndProc   = (WNDPROC)DefWindowProc;		        // WndProc Handles Messages
     wc.cbClsExtra    = 0;					// No Extra Window Data
     wc.cbWndExtra    = 0;					// No Extra Window Data
     wc.hInstance   = hInstance;			        // Set The Instance
     wc.hIcon	    = LoadIcon(NULL, IDI_WINLOGO);		// Load The Default Icon
     wc.hCursor	    = LoadCursor(NULL, IDC_ARROW);	        // Load The Arrow Pointer
     wc.hbrBackground = NULL;					// No Background Required For GL
     wc.lpszMenuName  = NULL;					// We Don't Want A Menu
     wc.lpszClassName = "OpenSG Tile";				// Set The Class Name
     
     if (!RegisterClass(&wc)) { // Attempt To Register The Window Class
       FWARNING(("TiledSupport::createWindows: Failed To Register The Window Class!\n"));
       return false;  
     }
   }

   RECT mClientRect;
   mClientRect.left   = 10;
   mClientRect.top    = 10; 
   mClientRect.right  = mClientRect.left + win_width;
   mClientRect.bottom = mClientRect.top  + win_height;

   DWORD dwStyle   = WS_OVERLAPPEDWINDOW;				// Windows Style
   DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;		// Window Extended Style
   //AdjustWindowRectEx(&mClientRect, dwStyle, FALSE, dwExStyle);	// Adjust WindowRect To True Size Including Decorations

   GLuint PixelFormat; // Holds The Results After Searching For A Match

   // open one window
   FWARNING(("TiledSupport::createWindows: open window\n"));
   // Create The Window
   hWnd = CreateWindowEx(dwExStyle,			// Extended Style For The Window
			    "OpenSG Tile",		// Class Name
			    "Tiles",  		        // Window Title
			    dwStyle |			// Defined Window Style
			    WS_CLIPSIBLINGS |		// Required Window Style
			    WS_CLIPCHILDREN,		// Required Window Style
			    mClientRect.left,
			    mClientRect.top,  	// Window Position
			    win_width,	        // Calculate Window Width
			    win_height,	        // Calculate Window Height
			    NULL,			// No Parent Window
			    NULL,			// No Menu
			    hInstance,		        // Instance
			    NULL);
   if (!hWnd) {			// Pass this-Pointer To WM_CREATE
       killGLWindow(0); // Reset The Display
       FWARNING(("TiledSupport::createWindows: Window Creation Error!\n"));
       return false;	
   }

   ShowWindow(hWnd, SW_SHOW); // Show The Window
   //SetForegroundWindow(hWnd); // Slightly Higher Priority
   //ResizeGLScene(width, height); // Set Up Our Perspective GL Screen

   hDC = GetDC(hWnd);
   if (hDC == 0) {							// Did We Get A Device Context?
       killGLWindow(0);								// Reset The Display
       FWARNING(("TiledSupport::createWindows: Can't Create A GL Device Context!\n"));
       return false;	
   }

   static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR),  //  size of this pfd  
					1,                     // version number  
					PFD_DRAW_TO_WINDOW |   // support window  
					PFD_SUPPORT_OPENGL |   // support OpenGL  
					PFD_DOUBLEBUFFER,      // double buffered  
					PFD_TYPE_RGBA,         // RGBA type  
					24,                    // 24-bit color depth  
					0, 0, 0, 0, 0, 0,      // color bits ignored  
					0,                     // no alpha buffer  
					0,                     // shift bit ignored  
					0,                     // no accumulation buffer  
					0, 0, 0, 0,            // accum bits ignored  
					32,                    // 32-bit z-buffer      
					0,                     // no stencil buffer  
					0,                     // no auxiliary buffer  
					PFD_MAIN_PLANE,        // main layer  
					0,                     // reserved  
					0, 0, 0                // layer masks ignored  
   }; 
   PixelFormat = ChoosePixelFormat(hDC, (const PIXELFORMATDESCRIPTOR*)&pfd);
   if (PixelFormat == 0) { 
      // Did Windows Find A Matching Pixel Format?
      killGLWindow(0); // Reset The Display
      FWARNING(("TiledSupport::createWindows: Can't Find A Suitable PixelFormat!\n"));
      return false;	
   }

   if (!SetPixelFormat(hDC, PixelFormat, (const PIXELFORMATDESCRIPTOR*)&pfd)) { 
      // Are We Able To Set The Pixel Format?   
      killGLWindow(0); // Reset The Display
      FWARNING(("TiledSupport::createWindows: Can't Set The PixelFormat!\n"));
      return false;	
   }   
   ShowWindow(hWnd, SW_SHOW); // Show The Window
   hRC = wglCreateContext(hDC);
   if (hRC == 0) { 
      // Are We Able To Get A Rendering Context?
      killGLWindow(0); // Reset The Display
      FWARNING(("TiledSupport::createWindows: Can't Create A GL Rendering Context!\n"));
      return false;	
   }
   makeCurrent(0);
}

int main(int argc, char **argv)
{
    OSG::ChangeList::setReadWriteDefault(true);
    OSG::osgInit(argc,argv);
    // GLUT init
    glutInit           (&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);

    glutInitWindowSize (500, 500);
    winId = glutCreateWindow("OpenSG");

    glutReshapeFunc (NULL);
    glutDisplayFunc (display);
    glutIdleFunc    (display);
    glutMouseFunc   (mouse);
    glutMotionFunc  (motion);
    glutKeyboardFunc(keyboard);

    win = OSG::GLUTWindow::create();
    win->setGlutId(winId);
    win->init();
    win->resize(500, 500);

    // create OSG objects
    createWindow();
    // create OSG objects
    win2 = OSG::WIN32Window::create();
    win2->editSFHwnd() ->setValue(hWnd);
    win2->editSFHdc()  ->setValue(hDC);
    win2->editSFHglrc()->setValue(hRC);
    ract = OSG::RenderAction::create();
    ract->setVolumeDrawing(true);
    win2->init();
    // very important for the size of viewports
    win2->resize(win_width, win_height);

    // very important: a context can only be current on one thread
    makeCurrent(-1);

    // create the scene
    OSG::NodeUnrecPtr scene = OSG::makeCoredNode<OSG::Group>();

#if 1
    std::cout << "load background" << std::endl;
    OSG::NodeRecPtr box = loadBackground();
    scene->addChild(box);
    std::cout << "done." << std::endl;
#endif
    scene->addChild(OSG::makeTorus(1.0f, 2.0f, 5, 5));

    // create the SimpleSceneManager helper
    mgr = new OSG::SimpleSceneManager;
    // create the window and initial camera/viewport
    mgr->setWindow(win );
    // tell the manager what to manage
    mgr->setRoot  (scene);

    // create shared OSG elements
    OSG::SolidBackgroundRecPtr bg = OSG::SolidBackground::create();
    bg->setColor(OSG::Color3f(0.5f, 0.0f, 0.0f));

    OSG::CameraUnrecPtr   cam  = mgr->getCamera();
    OSG::NodeUnrecPtr     root = mgr->getInternalRoot(); 
    OSG::ViewportRecPtr   np = OSG::Viewport::create();
    np->setCamera    (cam);
    np->setRoot      (root);
    np->setSize      (0, 0, 1, 1);
    np->setBackground(bg);
    //np->addForeground(fg);
    win2->addPort(np);

    OSG::Thread::getCurrentChangeList()->commitChanges();
    // show the whole scene
    mgr->showAll();

    pAppThread = static_cast<OSG::Thread *>(OSG::Thread::getCurrent());

    // instead start a new thread which runs the loop
    pDrawThread = OSG::Thread::get("render", 0);

    pSyncBarrier = OSG::Barrier::get("sync", 0);

#if 1
    pDrawThread->runFunction(::ThreadProc, // thread function
			1,            // aspect id
			NULL);        // thread argument
#endif

    pSyncBarrier->enter(2);
    pSyncBarrier->enter(2);

    OSG::Thread::getCurrentChangeList()->clear();

    // GLUT main loop
    glutMainLoop ();

    return 0;
}

------------------------------------------------------------------------------
Learn Windows Azure Live!  Tuesday, Dec 13, 2011
Microsoft is holding a special Learn Windows Azure training event for 
developers. It will provide a great way to learn Windows Azure and what it 
provides. You can attend the event by watching it streamed LIVE online.  
Learn more at http://p.sf.net/sfu/ms-windowsazure
_______________________________________________
Opensg-users mailing list
Opensg-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensg-users

Reply via email to