VTK: rotate an actor programmatically while vtkRenderWindowInteractor is active
I am trying to rotate vtkActor
with vtkActor::RotateZ
and then call vtkRenderWindow::Render
. It works fine (it rotates the actor), but I can't move, resize, or even focus the window.
I suspected it was caused by not catching operating system events, so I added to the table vtkRenderWindowInteractor
. Now I can move, resize and focus the window, but the actor no longer rotates.
I have highlighted the code in the snippet below, comment out line 43 to see both effects:
renderWindowInteractor->Start();
I am building VTK 6.2 using mingw-w64 (GCC 4.9.1), running on Windows 8.1. I have uploaded the code to this repo with a little CMake tweak so you can test it easily.
Thank you for your help!
constexpr float planeWidth = 200.0f;
constexpr float planeHeight = 100.0f;
int main()
{
auto renderer = vtkRenderer::New();
// Create render window
auto renWin = vtkRenderWindow::New();
renWin->AddRenderer(renderer);
renWin->SetSize(600,600);
// Create a plane
auto texturedPlane = vtkActor::New();
auto plane = vtkPlaneSource::New();
plane->SetOrigin(0, planeHeight, 0);
plane->SetPoint1(planeWidth, planeHeight, 0);
plane->SetPoint2(0, 0, 0);
auto planeMapper = vtkPolyDataMapper::New();
planeMapper->SetInputConnection(plane->GetOutputPort());
texturedPlane->SetMapper(planeMapper);
texturedPlane->SetOrigin(planeWidth / 2, planeHeight, 0);
renderer->AddActor(texturedPlane);
renderer->ResetCamera();
// Create a RenderWindowInteractor
auto renderWindowInteractor = vtkRenderWindowInteractor::New();
renderWindowInteractor->SetRenderWindow(renWin);
renderWindowInteractor->Start(); // <-- Comment this line!
// Render
float rot = 0.0f;
while(true)
{
texturedPlane->SetOrientation(0,0,0);
texturedPlane->RotateZ(rot++);
renWin->Render();
}
}
Solved to use asdfasdf solution: (Code in this repo )
constexpr float planeWidth = 200.0f;
constexpr float planeHeight = 100.0f;
vtkActor * texturedPlane;
vtkRenderWindowInteractor * renderWindowInteractor;
vtkRenderWindow * renWin;
float rot = 0.0f;
class RotateCommand : public vtkCommand
{
public:
vtkTypeMacro(RotateCommand, vtkCommand);
static RotateCommand * New()
{
return new RotateCommand;
}
void Execute(vtkObject * vtkNotUsed(caller),
unsigned long vtkNotUsed(eventId),
void * vtkNotUsed(callData))
{
texturedPlane->SetOrientation(0,0,0);
texturedPlane->RotateZ(rot++);
renWin->Render();
}
};
int main()
{
auto renderer = vtkRenderer::New();
// Create render window
renWin = vtkRenderWindow::New();
renWin->AddRenderer(renderer);
renWin->SetSize(600,600);
// Create a plane
texturedPlane = vtkActor::New();
auto plane = vtkPlaneSource::New();
plane->SetOrigin(0, planeHeight, 0);
plane->SetPoint1(planeWidth, planeHeight, 0);
plane->SetPoint2(0, 0, 0);
auto planeMapper = vtkPolyDataMapper::New();
planeMapper->SetInputConnection(plane->GetOutputPort());
texturedPlane->SetMapper(planeMapper);
texturedPlane->SetOrigin(planeWidth / 2, planeHeight, 0);
renderer->AddActor(texturedPlane);
renderer->ResetCamera();
// Create a RenderWindowInteractor
renderWindowInteractor = vtkRenderWindowInteractor::New();
renderWindowInteractor->SetRenderWindow(renWin);
renderWindowInteractor->Initialize();
renderWindowInteractor->CreateRepeatingTimer(1);
RotateCommand * rotateCallback = RotateCommand::New();
renderWindowInteractor->AddObserver(vtkCommand::TimerEvent, rotateCallback );
renderWindowInteractor->Start();
}
source to share
Hack part of the problem.
vtkRenderWindowInteractor * renderWindowInteractor;
constexpr float planeWidth = 200.0f;
constexpr float planeHeight = 100.0f;
class CommandSubclass2 : public vtkCommand
{
public:
vtkTypeMacro(CommandSubclass2, vtkCommand);
static CommandSubclass2 *New()
{
return new CommandSubclass2;
}
void Execute(vtkObject *vtkNotUsed(caller), unsigned long vtkNotUsed(eventId),
void *vtkNotUsed(callData))
{
std::cout << "timer callback" << std::endl;
renderWindowInteractor->ExitCallback();
}
};
int main()
{
auto renderer = vtkRenderer::New();
// Create render window
auto renWin = vtkRenderWindow::New();
renWin->AddRenderer(renderer);
renWin->SetSize(600,600);
// Create a plane
auto texturedPlane = vtkActor::New();
auto plane = vtkPlaneSource::New();
plane->SetOrigin(0, planeHeight, 0);
plane->SetPoint1(planeWidth, planeHeight, 0);
plane->SetPoint2(0, 0, 0);
auto planeMapper = vtkPolyDataMapper::New();
planeMapper->SetInputConnection(plane->GetOutputPort());
texturedPlane->SetMapper(planeMapper);
texturedPlane->SetOrigin(planeWidth / 2, planeHeight, 0);
renderer->AddActor(texturedPlane);
renderer->ResetCamera();
// Create a RenderWindowInteractor
renderWindowInteractor = vtkRenderWindowInteractor::New();
renderWindowInteractor->SetRenderWindow(renWin);
renderWindowInteractor->Initialize();
renderWindowInteractor->CreateRepeatingTimer(1);
vtkSmartPointer<CommandSubclass2> timerCallback = vtkSmartPointer<CommandSubclass2>::New();
renderWindowInteractor->AddObserver ( vtkCommand::TimerEvent, timerCallback );
// Render
float rot = 0.0f;
while(true)
{
renderWindowInteractor->Start(); // <-- Comment this line!
texturedPlane->SetOrientation(0,0,0);
texturedPlane->RotateZ(rot++);
renWin->Render();
}
}
Sorry if I didn't give you another answer, but since this solution is pretty bad, I was waiting for someone else to find a better solution, but it seems like no one answered you, so what would I do.
You can very much guess what it does. Every 1ms after the interaction starts, a callback is called, which will stop the interaction and make a rotation.
source to share