Display text on 3D stereoscopic views

How can I display text in pop-up 3D views?

Steps I follow:

  1. I create and show a right and left view with the following code:
layoutName = "LeftEyeView"
layoutLabel = "Left Eye"
layoutColor = [1.0, 1.0, 0.0]

viewOwnerNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScriptedModuleNode")
                    
# Create MRML node
viewLogic = slicer.vtkMRMLViewLogic()
viewLogic.SetMRMLScene(slicer.mrmlScene)
            
# Left node
viewNodeLeft = viewLogic.AddViewNode(layoutName)
viewNodeLeft.SetLayoutLabel(layoutLabel)
viewNodeLeft.SetLayoutColor(layoutColor)
viewNodeLeft.SetAndObserveParentLayoutNodeID(viewOwnerNode.GetID())
viewNodeLeft.SetStereoType(3)# Quadbuffer Stereo layout 1 is left eye (dont know why)

# Create widget
self.viewWidgetLeft = slicer.qMRMLThreeDWidget()
self.viewWidgetLeft.setMRMLScene(slicer.mrmlScene)
self.viewWidgetLeft.setMRMLViewNode(viewNodeLeft)      
print("Left widget created")
self.viewWidgetLeft.show()       

  1. I display some text on the 3D view from the Slicer UI
# Get the 3D view renderer
self.layoutManager = slicer.app.layoutManager()
self.threeDView = self.layoutManager.threeDWidget(0).threeDView()
self.renderer = self.threeDView.renderWindow().GetRenderers().GetFirstRenderer()

# Create a text actor to display the text
self.textActor = vtk.vtkTextActor()
# Position the text actor in the corner
self.textActor.GetPositionCoordinate().SetCoordinateSystemToNormalizedViewport()
self.textActor.SetPosition(0.8, 0.9) 

# Add the text actor to the renderer
self.renderer.AddActor2D(self.textActor )
  1. In order to add the text in the created left and right views, I need to access those views. Using “layoutManager.threeDWidget(–viewNumber–).threeDView()” does not let me display any text in those views.

The view nodes I actually have are:
View1 (from the UI): vtkMRMLViewNode1
View (left eye): vtkMRMLViewNodeLeftEyeView
View_1 (right eye): vtkMRMLViewNodeRightEyeView

How can I access the render windows of those views in order to be able to display text in those?

The layout manager only manages the views in the layout. Since you create the other views and widgets you can directly use thise objects.

Note that you cannot use 2D actor to display anything in a stereo display, because inconsistent stereo parallax and occlusion (this most often causes double vision for the user). You can use 3D text actors instead.

Thanks a lot for the quick answer and explanation!

I created a 3D actor to display the text, but it doesn’t display it in the other views:

the code I used:
renderer = slicer.app.layoutManager().threeDWidget(0).threeDView().renderWindow().GetRenderers().GetFirstRenderer()
text_actor = vtk.vtkTextActor3D()
renderer.AddActor(text_actor)

Also, when using threeDWidget(1) or (2), there was nothing displayed in the right and left views.

Therefore, as you suggested, I tried to use the views I create directly instead of retrieving them from the layout manager. However, I can only get the camera and the views, and there is no method for adding (3D) actors that way. Neither with the “viewOwnerNode” that I create.

Is there any other way to access the render windows of the nodes I create?

You directly access the renderer by using low-level calls. If you add an actor in a view, it will be only added in that view. If you want to add an object that is displayed in all views automatically then you can create a polydata from text using vtkTextSource and display it using a model node.

The layout manager only manages the views in the layout. The views that are outside the view layout are inaccessible for the layout manager, but it is not a problem at all, because you create all these other views and widgets and so you can directly use these objects. For example, you can get the renderer from the view widget you created:

renderer = viewWidget.threeDView().renderWindow().GetRenderers().GetFirstRenderer()