[vtkusers] Multiple renderwindows/interactor concurrently?

a.meijster at rc.rug.nl a.meijster at rc.rug.nl
Mon Jul 5 10:55:44 EDT 2004



Hi all,

I have the following problem. I want to make a vtk 
program in which I want several windows to be opened,
each with its own interactor. Besides, I want the main 
program to continue computing. How can I do this? It
appears to me that I can have only one interactor (iren) 
active, since iren->Start() does not return. 
So, I decided to use pthreads, and made the following code.
This runs only under Unix with X11, but that's fine
for the time being. The strange thing is that this 
code runs, but sometimes interaction hangs for a while.
I guess threads are eating eachothers events, or something
like that. 

Does anyone see my error, or has a better solution?

Regards,

  Arnold Meijster



//
// This example introduces the concepts of interaction into the
// C++ environment. A different interaction style (than
// the default) is defined. 
// 

#include <X11/Xlib.h>
#include <pthread.h>

// First include the required header files for the VTK classes we are
using.
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkCamera.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkInteractorStyleTrackballCamera.h"
#include "vtkCommand.h"

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void Lock() {
  pthread_mutex_lock(&mutex);
}

void Unlock() {
  pthread_mutex_unlock(&mutex);
}

// Callback for the interaction
class vtkLockCallback : public vtkCommand
{
public:
  static vtkLockCallback *New()
    { return new vtkLockCallback; }
  virtual void Execute(vtkObject *caller, unsigned long, void*)
    {
      Lock();
    }
};

class vtkUnlockCallback : public vtkCommand
{
public:
  static vtkUnlockCallback *New()
    { return new vtkUnlockCallback; }
  virtual void Execute(vtkObject *caller, unsigned long, void*)
    {
      Unlock();
    }
};


void *Thread(void *arg) 
{
  // 
  // Next we create an instance of vtkConeSource and set some of its
  // properties. The instance of vtkConeSource "cone" is part of a
  // visualization pipeline (it is a source process object); it
produces data
  // (output type is vtkPolyData) which other filters may process.
  //
  vtkConeSource *cone = vtkConeSource::New();
  cone->SetHeight( 3.0 );
  cone->SetRadius( 1.0 );
  cone->SetResolution( 10 );
  
  // 
  // In this example we terminate the pipeline with a mapper process
object.
  // (Intermediate filters such as vtkShrinkPolyData could be inserted
in
  // between the source and the mapper.)  We create an instance of
  // vtkPolyDataMapper to map the polygonal data into graphics
primitives. We
  // connect the output of the cone souece to the input of this mapper.
  //
  vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New();
  coneMapper->SetInput( cone->GetOutput() );

  // 
  // Create an actor to represent the cone. The actor orchestrates
rendering
  // of the mapper's graphics primitives. An actor also refers to
properties
  // via a vtkProperty instance, and includes an internal
transformation
  // matrix. We set this actor's mapper to be coneMapper which we
created
  // above.
  //
  vtkActor *coneActor = vtkActor::New();
  coneActor->SetMapper( coneMapper );

  //
  // Create the Renderer and assign actors to it. A renderer is like a
  // viewport. It is part or all of a window on the screen and it is
  // responsible for drawing the actors it has.  We also set the
background
  // color here.
  //
  vtkRenderer *ren1= vtkRenderer::New();
  ren1->AddActor( coneActor );
  ren1->SetBackground( 0.1, 0.2, 0.4 );

  //
  // Finally we create the render window which will show up on the
screen.
  // We put our renderer into the render window using AddRenderer. We
also
  // set the size to be 300 pixels by 300.
  //
  vtkRenderWindow *renWin = vtkRenderWindow::New();
  renWin->AddRenderer( ren1 );
  renWin->SetSize( 300, 300 );

  // 
  // The vtkRenderWindowInteractor class watches for events (e.g.,
keypress,
  // mouse) in the vtkRenderWindow. These events are translated into
  // event invocations that VTK understands (see
VTK/Common/vtkCommand.h
  // for all events that VTK processes). Then observers of these VTK
  // events can process them as appropriate.
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
  iren->SetRenderWindow(renWin);

  //
  // By default the vtkRenderWindowInteractor instantiates an instance
  // of vtkInteractorStyle. vtkInteractorStyle translates a set of
events
  // it observes into operations on the camera, actors, and/or
properties
  // in the vtkRenderWindow associated with the
vtkRenderWinodwInteractor. 
  // Here we specify a particular interactor style.
  vtkInteractorStyleTrackballCamera *style = 
    vtkInteractorStyleTrackballCamera::New();
  iren->SetInteractorStyle(style);

  //
  // Unlike the previous scripts where we performed some operations and
then
  // exited, here we leave an event loop running. The user can use the
mouse
  // and keyboard to perform the operations on the scene according to
the
  // current interaction style. When the user presses the "e" key, by
default
  // an ExitEvent is invoked by the vtkRenderWindowInteractor which is
caught
  // and drops out of the event loop (triggered by the Start() method
that
  // follows.
  //
  Lock();
  iren->Initialize();
  Unlock();

  iren->Start();
  
  // 
  // Final note: recall that an observers can watch for particular
events and
  // take appropriate action. Pressing "u" in the render window causes
the
  // vtkRenderWindowInteractor to invoke a UserEvent. This can be
caught to
  // popup a GUI, etc. So the Tcl Cone5.tcl example for an idea of how
this
  // works.

  //
  // Free up any objects we created. All instances in VTK are deleted
by
  // using the Delete() method.
  //
  cone->Delete();
  coneMapper->Delete();
  coneActor->Delete();
  ren1->Delete();
  renWin->Delete();
  iren->Delete();
  style->Delete();

  return NULL;
}


int main (int argc, char **argv) {
  XInitThreads();

  pthread_t  th1, th2;

  pthread_create(&th1, NULL, Thread, NULL);
  pthread_create(&th2, NULL, Thread, NULL);

  while (1) {
    /* Here I want to do some computation */
    printf ("*"); 
    fflush(stdout);
    sleep(1);
  }
  printf ("pthreadjoin th1=%d\n", pthread_join(th1, NULL));
  printf ("pthreadjoin th2=%d\n", pthread_join(th2, NULL));


  return 0;
}

========================================================
Arnold Meijster
Centre for High Performance Computing & Visualisation,
Nettelbosje 1,
9747 AJ Groningen, Netherlands

e-mail: a.meijster at rc.rug.nl
tel:    +31 50 363 9246



More information about the vtkusers mailing list