VTK 9.5.1を使おうとしたところ、今までのwxWidgets+VTKのコードで動かなくなっていた。
なんとかWindows+wxWidgetsでVTK9.5.1での表示ができるようになった。

#include <wx/wxprec.h> #include <wx/glcanvas.h> #include <wx/frame.h> #ifndef WX_PRECOMP #include <wx/wx.h> #endif #include <GL/gl.h> #pragma comment(lib, "opengl32.lib") #include <iostream> //VTK_MODULE_INITに必要 #include <vtkAutoInit.h> #include <vtkOutputWindow.h> #include <vtkSmartPointer.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkActor.h> #include <vtkPolyDataMapper.h> #include <vtkCylinderSource.h> #include <vtkInteractorStyleTrackballCamera.h> #include <vtkWin32OpenGLRenderWindow.h> #include <vtkWin32RenderWindowInteractor.h> #include <vtkConeSource.h> VTK_MODULE_INIT(vtkRenderingOpenGL2); VTK_MODULE_INIT(vtkInteractionStyle); vtkSmartPointer<vtkActor> CreateCone() { vtkSmartPointer<vtkConeSource> coneSource; coneSource = vtkSmartPointer<vtkConeSource>::New(); vtkSmartPointer<vtkPolyDataMapper> mapper; mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(coneSource->GetOutputPort()); vtkSmartPointer<vtkActor> actor; actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); return actor; } class MyGLCanvas : public wxGLCanvas { public: MyGLCanvas(wxFrame* parent,int* attribList = NULL); private: wxGLContext* m_context; // OpenGL context ////////////////////////////////////////// vtkNew<vtkWin32OpenGLRenderWindow> _renderWindow; vtkNew<vtkWin32RenderWindowInteractor> _interactor; vtkNew<vtkRenderer> _renderer; ////////////////////////////////////////// bool vtk_inited = false; ////////////////////////////////////////// // OpenGLコンテキストの作成をしてVTKに貸与する関数 void InitVTKFromCurrentContext(); ////////////////////////////////////////// // マウスイベントを処理 int last_x_ = 0, last_y_ = 0; void OnLeftDown(wxMouseEvent& e); void OnLeftUp(wxMouseEvent& e); void OnRightDown(wxMouseEvent& e); void OnRightUp(wxMouseEvent& e); void OnMiddleDown(wxMouseEvent& e); void OnMiddleUp(wxMouseEvent& e); void OnMotion(wxMouseEvent& e); void OnMouseWheel(wxMouseEvent& e); ////////////////////////////////////////// void OnPaint(wxPaintEvent& evt); }; MyGLCanvas::MyGLCanvas(wxFrame* parent, int* attribList) : wxGLCanvas(parent, wxID_ANY, attribList) { Bind(wxEVT_PAINT, &MyGLCanvas::OnPaint, this); m_context = new wxGLContext(this); SetBackgroundStyle(wxBG_STYLE_CUSTOM); Bind(wxEVT_LEFT_DOWN, &MyGLCanvas::OnLeftDown, this); Bind(wxEVT_LEFT_UP, &MyGLCanvas::OnLeftUp, this); Bind(wxEVT_RIGHT_DOWN, &MyGLCanvas::OnRightDown, this); Bind(wxEVT_RIGHT_UP, &MyGLCanvas::OnRightUp, this); Bind(wxEVT_MIDDLE_DOWN, &MyGLCanvas::OnMiddleDown, this); Bind(wxEVT_MIDDLE_UP, &MyGLCanvas::OnMiddleUp, this); Bind(wxEVT_MOTION, &MyGLCanvas::OnMotion, this); Bind(wxEVT_MOUSEWHEEL, &MyGLCanvas::OnMouseWheel, this); } void MyGLCanvas::OnLeftDown(wxMouseEvent& e) { SetFocus(); CaptureMouse(); last_x_ = e.GetX(); last_y_ = e.GetY(); _interactor->SetEventInformationFlipY(last_x_, last_y_, e.ControlDown(), e.ShiftDown()); _interactor->InvokeEvent(vtkCommand::LeftButtonPressEvent); } void MyGLCanvas::OnLeftUp(wxMouseEvent& e) { last_x_ = e.GetX(); last_y_ = e.GetY(); ReleaseMouse(); _interactor->SetEventInformationFlipY(last_x_, last_y_, e.ControlDown(), e.ShiftDown()); _interactor->InvokeEvent(vtkCommand::LeftButtonReleaseEvent); } void MyGLCanvas::OnRightDown(wxMouseEvent& e) { last_x_ = e.GetX(); last_y_ = e.GetY(); CaptureMouse(); _interactor->SetEventInformationFlipY(last_x_, last_y_, e.ControlDown(), e.ShiftDown()); _interactor->InvokeEvent(vtkCommand::RightButtonPressEvent); } void MyGLCanvas::OnRightUp(wxMouseEvent& e) { last_x_ = e.GetX(); last_y_ = e.GetY(); ReleaseMouse(); _interactor->SetEventInformationFlipY(last_x_, last_y_, e.ControlDown(), e.ShiftDown()); _interactor->InvokeEvent(vtkCommand::RightButtonReleaseEvent); } void MyGLCanvas::OnMiddleDown(wxMouseEvent& e) { last_x_ = e.GetX(); last_y_ = e.GetY(); CaptureMouse(); _interactor->SetEventInformationFlipY(last_x_, last_y_, e.ControlDown(), e.ShiftDown()); _interactor->InvokeEvent(vtkCommand::MiddleButtonPressEvent); } void MyGLCanvas::OnMiddleUp(wxMouseEvent& e) { last_x_ = e.GetX(); last_y_ = e.GetY(); ReleaseMouse(); _interactor->SetEventInformationFlipY(last_x_, last_y_, e.ControlDown(), e.ShiftDown()); _interactor->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent); } void MyGLCanvas::OnMotion(wxMouseEvent& e) { last_x_ = e.GetX(); last_y_ = e.GetY(); _interactor->SetEventInformationFlipY(last_x_, last_y_, e.ControlDown(), e.ShiftDown()); _interactor->InvokeEvent(vtkCommand::MouseMoveEvent); } void MyGLCanvas::OnMouseWheel(wxMouseEvent& e) { last_x_ = e.GetX(); last_y_ = e.GetY(); _interactor->SetEventInformationFlipY(last_x_, last_y_, e.ControlDown(), e.ShiftDown()); if (e.GetWheelRotation() > 0) _interactor->InvokeEvent(vtkCommand::MouseWheelForwardEvent); else _interactor->InvokeEvent(vtkCommand::MouseWheelBackwardEvent); } void MyGLCanvas::InitVTKFromCurrentContext() { // wxのGLを現在化 wxPaintDC dc(this); SetCurrent(*m_context); // Win32ハンドル取得 HWND hwnd = this->GetHandle(); HDC hdc = dc.GetHDC(); HGLRC hrc = m_context->GetGLRC(); // wxWidgetsが作ったコンテキストをVTKへ貸与 _renderWindow->SetWindowId(hwnd); _renderWindow->SetDeviceContext(hdc); _renderWindow->SetContextId(hrc); _renderWindow->InitializeFromCurrentContext(); // レンダラの設定 _renderWindow->AddRenderer(_renderer); _interactor->SetRenderWindow(_renderWindow); _interactor->Initialize(); _interactor->Enable(); // マウスイベントを設定. auto style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New(); style->SetDefaultRenderer(_renderer); _interactor->SetInteractorStyle(style); // レンダリング _renderer->SetBackground(1.1, 0.2, 0.3); _renderer->AddActor(CreateCone()); vtk_inited = true; } void MyGLCanvas::OnPaint(wxPaintEvent& evt) { if (!IsShown()) return; if (!vtk_inited) InitVTKFromCurrentContext(); SetCurrent(*m_context); _renderWindow->Render(); } class MyFrame : public wxFrame { public: MyFrame(const wxString& title, int xpos, int ypos, int width, int height); ~MyFrame(); void OnSize(wxSizeEvent& event); MyGLCanvas* m_canvas = NULL; }; MyFrame::MyFrame(const wxString& title, int xpos, int ypos, int width, int height) : wxFrame((wxFrame*)NULL, -1, title, wxPoint(xpos, ypos), wxSize(width, height)) { int args[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0 }; m_canvas = new MyGLCanvas(this, args); Bind(wxEVT_SIZE, &MyFrame::OnSize, this); } void MyFrame::OnSize(wxSizeEvent& event) { m_canvas->SetSize(event.GetSize()); } MyFrame::~MyFrame() { delete m_canvas; } class MyApp : public wxApp { public: bool OnInit(); }; bool MyApp::OnInit() { // VTKのデバッグ出力ウィンドウを表示しない vtkOutputWindow::SetGlobalWarningDisplay(0); MyFrame* frame = new MyFrame(wxT("wxWidgets OpenGL"), 50, 50, 400, 400); frame->Show(); return true; } IMPLEMENT_APP(MyApp)
OnSizeを以下のように記述。
void MyGLCanvas::OnSize(wxSizeEvent& e) { if (!vtk_inited || !IsShownOnScreen()) return; int w = 0, h = 0; GetClientSize(&w, &h); // HiDPI 対応(MSW の例) int pw = w, ph = h; #ifdef __WXMSW__ double scale = GetContentScaleFactor(); pw = static_cast<int>(std::lround(w * scale)); ph = static_cast<int>(std::lround(h * scale)); #endif // 次のペイントで描画 Refresh(false); e.Skip(); // 既定処理も通す }