I am developing a 3D application based on VTK and QtQuick. I am trying to use vtkCameraOrientationWidget and followed example here (https://kitware.github.io/vtk-examples/site/Cxx/PolyData/Curvatures/). To use vtkCameraOrientationWidget, it is basically three lines of code:
vtkNew<vtkCameraOrientationWidget> camOrientManipulator;
camOrientManipulator->SetParentRenderer(renderer);
// Enable the widget.
camOrientManipulator->On();
But there is no interaction (i.e., mouse click on the handle to change camera view). I can confirm that my vtkstyle get all the mouse events passed from QEvent. Any help is appreciated!
I donāt use vtkCameraOrientationWidget, but something else from the same family. I setup my VTK widget with a code like this (the last four lines of code are the ones that make the thing work):
Thanks for your reply. vtkOrientationMarkerWidget use a different design than vtkCameraOrientationWidget.
For vtkCameraOrientationWidget, SetInteractor() actually happens inside SetParentRenderer()
What I need to do is just to have a widget where I can click on a set of handles to actively change the camera view in my renderer. This is exactly what vtkCameraOrientationWidget does. Now in my codebase, I can get it work except for handle interactions. For some reasons, vtkCameraOrientationWidget doesnāt receive my mouse events.
Now I am trying vtkOrientationMarkerWidget which can receive my events but I have to implement the control by myself (i.e., click on the widget, pick the corresponding cell, then do something).
I donāt have a _vtkwidget as QVTKOpenGLWidget.
What is _vtkwidget for?
In your example, if I do _vtkAxesWidget->SetInteractor(_myRenderWindow->GetInteractor()); rather than _vtkAxesWidget->SetInteractor(_vtkwidget->GetRenderWindow()->GetInteractor());. Isnāt it the same thing?
And it works fine. I suspect that my issue with vtkCameraOrientationWidget is from SetParentRender() design which is different than other widgets.
For other widgets, the workflow is 1) setup widget representation. 2) setup widget interactor which is the interactor in my renderwindow. 3) enable widget. So there is only one renderer and one layer in renderwindow and the widget is rendered in this renderer.
For vtkCameraOrientationWidget, it is a little bit different as it creates a second renderer which is overlaid on my main renderer. So my renderwindow has two layers: layer 0 for my main renderer and layer 1 for a new renderer which renders vtkCameraOrientationWidget. Per instruction, I just have to do
vtkNew<vtkCameraOrientationWidget> camOrientManipulator;
camOrientManipulator->SetParentRenderer(renderer);
// Enable the widget.
camOrientManipulator->On();
Everything that I described above just happened inside SetParentRenderer(renderer). But there is no interaction. This particular design doesnāt fit my QtQuick framework or at least I am missing something. I am really confused.
I also have two renderers in my program (the main one called _rendererMainScene and another for always-on-top actors such as labels called _rendererForeground). Hereās how I set everthing up (before adding actors):
_vtkwidget = new QVTKOpenGLWidget();
_rendererMainScene = vtkSmartPointer<vtkRenderer>::New();
// Create the renderer for always-on-top objects
// It attaches to the same camera of the main renderer
_rendererForeground = vtkSmartPointer<vtkRenderer>::New();
_rendererForeground->SetActiveCamera( _rendererMainScene->GetActiveCamera() );
_rendererForeground->SetLayer( 1 ); //layers greater than zero have no background and are rendered last.
_vtkwidget->SetRenderWindow(vtkGenericOpenGLRenderWindow::New());
_vtkwidget->GetRenderWindow()->AddRenderer(_rendererMainScene);
_vtkwidget->GetRenderWindow()->AddRenderer(_rendererForeground);
_vtkwidget->setFocusPolicy(Qt::StrongFocus);
//----------------------adding the orientation axes-------------------------
vtkSmartPointer<vtkAxesActor> axes = vtkSmartPointer<vtkAxesActor>::New();
_vtkAxesWidget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
_vtkAxesWidget->SetOutlineColor(0.9300, 0.5700, 0.1300);
_vtkAxesWidget->SetOrientationMarker(axes);
_vtkAxesWidget->SetInteractor(_vtkwidget->GetRenderWindow()->GetInteractor());
_vtkAxesWidget->SetViewport(0.0, 0.0, 0.2, 0.2);
_vtkAxesWidget->SetEnabled(1);
_vtkAxesWidget->InteractiveOn();
//--------------------------------------------------------------------------
// Customize event handling through a subclass of vtkInteractorStyleTrackballCamera.
// This allows picking and probing by clicking on objects in the scene, for example.
m_myInteractor = vtkSmartPointer<v3dMouseInteractor>::New();
m_myInteractor->setParentView3DWidget( this );
m_myInteractor->SetDefaultRenderer(_rendererMainScene);
_vtkwidget->GetRenderWindow()->GetInteractor()->SetInteractorStyle( m_myInteractor );
// Set callback for any event
vtkSmartPointer<vtkCallbackCommand> callBackCommand = vtkSmartPointer<vtkCallbackCommand>::New();
callBackCommand->SetCallback( rendererCallback );
callBackCommand->SetClientData((void*)this);
_rendererMainScene->AddObserver( vtkCommand::AnyEvent , callBackCommand ); // mp_ren is the vtkRenderer object.
// adjusts view so everything fits in the screen
_rendererMainScene->ResetCamera();
// add the VTK widget the layout
ui->frmViewer->layout()->addWidget(_vtkwidget);
Maybe this helps to pinpoint the problem with your code.
Anything amiss with how the objects are wired youāll end up with the mouse events not going to where they are supposed to.
SetParentRenderer() is supposed to wire everything for you, that is, to send mouse events to the target renderer so whenever you manipulate the vtkCameraOrientationWidget, the scene updates accordingly. Maybe the problem is on how two renderers coexist in the same render window. See the code I posted above on how two renderers can coexist so the can both display things and receive user input events through the same window.
I am the author of vtkCameraOrientationWidget and itās representation. Iāll be honest, I havenāt tested it in a QtQuick window yet. As a matter of fact I have never done any QtQuick development besides the basics in QtCreator.
Could you help me by answering these questions?
When you try to rotate the camera interactively in the main renderer (the viewport with your dataset (s)), does the camera rotate like usual?
When you do the above, does the widget also rotate and does it show some sort of synchronization with the main rendererās camera?
When you move mouse on top of the widget, do you see any of these visual changes in the widget?
a. A transparent greyish disk enclosing the widget
b. The color of the text (x or y or z) on the hovered grabber changes from black to white
I want to know if the widget is at least hot. Basically, for any interaction, it needs to get activated by hovering, which makes it hot.
It would be great if you could call Print on the widget and the interactor on any mouse click, move, release events. I would like to see the event flow.
I have no intention to change the source. I am kind of switching my main application back to QtWidget. I realized that I can inject QML element into my main QtWidget application.
and sets the number of layers to 2, which could mess up with the renderer which renders vtkCameraOrientationWidget .
Hmm, I think there is no need to worry about this because I safely preserve/increase the number of layers. See 83 - 84 and 100 - 101
Iāve seen this widget work in ParaView which already uses 2 layers (base layer +1 for the older pvAxes orientation widget) so it should not be an issue with layers afaik.
I assume because both the renderers QQuickVTKRenderWindow::m_dummyRenderer and vtkCameraOrientationWidget::DefaultRenderer live in the same layer and one overlaps the other, the events are not propagated to my widget. I have to investigate thisā¦
In ParaView, it might have worked because the old pvAxes orientation widget occupied a smaller viewport rectangle and did not overlap the widget rendererās viewport.