actorなどの生成まではスレッドでできるが、Render()関数などの呼び出しはメインスレッドで行わなければいけない。
VTKのメッセージループを使う限りはシグナルを送ったりということが簡単にできないので、OnTimerで定期的にRender()をする。
#include <iostream> #include <thread> //VTK_MODULE_INITに必要 #include <vtkAutoInit.h> #include <vtkSmartPointer.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkPolyDataMapper.h> #include <vtkSphereSource.h> #include <vtkCallbackCommand.h> #include <vtkCamera.h> #include <vtkActor.h> // #include "createpoly.hpp" //必須 VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle);
// 定期的に Render する void OnTimer(vtkObject* /*caller*/, unsigned long /*eventId*/, void* clientData, void* /*callData*/) { auto renderWindow = static_cast<vtkRenderWindow*>(clientData); if (renderWindow) { renderWindow->Render(); } }
// 停止フラグ std::atomic<bool> g_stop{ false };
// スレッド void work(vtkSmartPointer<vtkRenderer> renderer) { for (size_t i = 0; i < 100; i++) { // 乱数 double x = (std::rand() % 100) / 10.0 - 5.0; double y = (std::rand() % 100) / 10.0 - 5.0; double z = (std::rand() % 100) / 10.0 - 5.0; // 球体 vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New(); sphereSource->SetCenter(x,y,z); sphereSource->SetRadius(5.0); sphereSource->Update(); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(sphereSource->GetOutputPort()); actor->SetMapper(mapper); renderer->AddActor(actor); std::this_thread::sleep_for(std::chrono::seconds(1)); if(g_stop) break; } }
int main(int /*argc*/, char** /*argv*/) { auto renderer = vtkSmartPointer<vtkRenderer>::New(); renderer->ResetCamera(); renderer->GetActiveCamera()->SetPosition(0, 0, 100); ////////////////////////////////////// auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); ////////////////////////////////////// auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->AddRenderer(renderer); renderWindow->SetInteractor(interactor); renderWindow->Render(); auto cb = vtkSmartPointer<vtkCallbackCommand>::New(); cb->SetClientData(renderWindow); cb->SetCallback(OnTimer); interactor->AddObserver(vtkCommand::TimerEvent, cb); interactor->Initialize(); interactor->CreateRepeatingTimer(10); std::thread t1(work, renderer); interactor->Start(); //イベントループへ入る g_stop = true; t1.join(); return 0; }