// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkRenderWindow.h" #include "vtkCamera.h" #include "vtkCollection.h" #include "vtkCommand.h" #include "vtkGraphicsFactory.h" #include "vtkMath.h" #include "vtkNew.h" #include "vtkObjectFactory.h" #include "vtkPropCollection.h" #include "vtkRenderTimerLog.h" #include "vtkRenderWindowInteractor.h" #include "vtkRendererCollection.h" #include "vtkStereoCompositor.h" #include "vtkTimerLog.h" #include "vtkTransform.h" #include "vtkUnsignedCharArray.h" #include #include #include #include // for std::swap //------------------------------------------------------------------------------ VTK_ABI_NAMESPACE_BEGIN vtkObjectFactoryNewMacro(vtkRenderWindow); // Construct an instance of vtkRenderWindow with its screen size // set to 300x300, borders turned on, positioned at (0,0), double // buffering turned on, stereo capable off. vtkRenderWindow::vtkRenderWindow() { this->Borders = 1; this->Coverable = 0; this->FullScreen = 0; this->OldScreen[0] = this->OldScreen[1] = 0; this->OldScreen[2] = this->OldScreen[3] = 300; this->OldScreen[4] = 1; this->DoubleBuffer = 1; this->PointSmoothing = 0; this->LineSmoothing = 0; this->PolygonSmoothing = 0; this->StereoRender = 0; this->StereoType = VTK_STEREO_RED_BLUE; this->StereoCapableWindow = 0; this->AlphaBitPlanes = 0; this->StencilCapable = 0; this->Interactor = nullptr; this->DesiredUpdateRate = 0.0001; this->StereoBuffer = vtkSmartPointer::New(); this->ResultFrame = vtkSmartPointer::New(); this->SwapBuffers = 1; this->AbortRender = 0; this->InAbortCheck = 0; this->InRender = 0; this->NeverRendered = 1; this->Renderers = vtkRendererCollection::New(); this->NumberOfLayers = 1; this->CurrentCursor = VTK_CURSOR_DEFAULT; this->AnaglyphColorSaturation = 0.65f; this->AnaglyphColorMask[0] = 4; // red this->AnaglyphColorMask[1] = 3; // cyan this->AbortCheckTime = 0.0; this->CapturingGL2PSSpecialProps = 0; this->MultiSamples = 0; this->UseSRGBColorSpace = false; #ifdef VTK_DEFAULT_RENDER_WINDOW_OFFSCREEN this->ShowWindow = false; this->UseOffScreenBuffers = true; #endif this->DeviceIndex = 0; this->SharedRenderWindow = nullptr; this->CursorFileName = nullptr; } //------------------------------------------------------------------------------ vtkRenderWindow::~vtkRenderWindow() { this->SetInteractor(nullptr); this->SetSharedRenderWindow(nullptr); this->SetCursorFileName(nullptr); if (this->Renderers) { vtkRenderer* ren; vtkCollectionSimpleIterator rit; this->Renderers->InitTraversal(rit); while ((ren = this->Renderers->GetNextRenderer(rit))) { ren->SetRenderWindow(nullptr); } this->Renderers->Delete(); } } void vtkRenderWindow::SetMultiSamples(int val) { if (val == 1) { val = 0; } if (val == this->MultiSamples) { return; } this->MultiSamples = val; this->Modified(); } //------------------------------------------------------------------------------ // Create an interactor that will work with this renderer. vtkRenderWindowInteractor* vtkRenderWindow::MakeRenderWindowInteractor() { this->Interactor = vtkRenderWindowInteractor::New(); this->Interactor->SetRenderWindow(this); return this->Interactor; } void vtkRenderWindow::SetSharedRenderWindow(vtkRenderWindow* val) { if (this->SharedRenderWindow == val) { return; } if (this->SharedRenderWindow) { // this->ReleaseGraphicsResources(); this->SharedRenderWindow->UnRegister(this); } this->SharedRenderWindow = val; if (val) { val->Register(this); } } //------------------------------------------------------------------------------ // Set the interactor that will work with this renderer. void vtkRenderWindow::SetInteractor(vtkRenderWindowInteractor* rwi) { if (this->Interactor != rwi) { // to avoid destructor recursion vtkRenderWindowInteractor* temp = this->Interactor; this->Interactor = rwi; if (temp != nullptr) { temp->UnRegister(this); } if (this->Interactor != nullptr) { this->Interactor->Register(this); int isize[2]; this->Interactor->GetSize(isize); if (0 == isize[0] && 0 == isize[1]) { this->Interactor->SetSize(this->GetSize()); } if (this->Interactor->GetRenderWindow() != this) { this->Interactor->SetRenderWindow(this); } } } } //------------------------------------------------------------------------------ void vtkRenderWindow::SetPhysicalViewDirection(double x, double y, double z) { if (this->PhysicalViewDirection[0] != x || this->PhysicalViewDirection[1] != y || this->PhysicalViewDirection[2] != z) { this->PhysicalViewDirection[0] = x; this->PhysicalViewDirection[1] = y; this->PhysicalViewDirection[2] = z; this->InvokeEvent(vtkRenderWindow::PhysicalToWorldMatrixModified); this->Modified(); } } //------------------------------------------------------------------------------ void vtkRenderWindow::SetPhysicalViewDirection(double dir[3]) { this->SetPhysicalViewDirection(dir[0], dir[1], dir[2]); } //------------------------------------------------------------------------------ void vtkRenderWindow::SetPhysicalViewUp(double x, double y, double z) { if (this->PhysicalViewUp[0] != x || this->PhysicalViewUp[1] != y || this->PhysicalViewUp[2] != z) { this->PhysicalViewUp[0] = x; this->PhysicalViewUp[1] = y; this->PhysicalViewUp[2] = z; this->InvokeEvent(vtkRenderWindow::PhysicalToWorldMatrixModified); this->Modified(); } } //------------------------------------------------------------------------------ void vtkRenderWindow::SetPhysicalViewUp(double dir[3]) { this->SetPhysicalViewUp(dir[0], dir[1], dir[2]); } //------------------------------------------------------------------------------ void vtkRenderWindow::SetPhysicalTranslation(double x, double y, double z) { if (this->PhysicalTranslation[0] != x || this->PhysicalTranslation[1] != y || this->PhysicalTranslation[2] != z) { this->PhysicalTranslation[0] = x; this->PhysicalTranslation[1] = y; this->PhysicalTranslation[2] = z; this->InvokeEvent(vtkRenderWindow::PhysicalToWorldMatrixModified); this->Modified(); } } //------------------------------------------------------------------------------ void vtkRenderWindow::SetPhysicalTranslation(double trans[3]) { this->SetPhysicalTranslation(trans[0], trans[1], trans[2]); } //------------------------------------------------------------------------------ void vtkRenderWindow::SetPhysicalScale(double scale) { if (this->PhysicalScale != scale) { this->PhysicalScale = scale; this->InvokeEvent(vtkRenderWindow::PhysicalToWorldMatrixModified); this->Modified(); } } //------------------------------------------------------------------------------ void vtkRenderWindow::SetPhysicalToWorldMatrix(vtkMatrix4x4* matrix) { if (!matrix) { return; } vtkNew currentPhysicalToWorldMatrix; this->GetPhysicalToWorldMatrix(currentPhysicalToWorldMatrix); bool matrixDifferent = false; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (fabs(matrix->GetElement(i, j) - currentPhysicalToWorldMatrix->GetElement(i, j)) >= 1e-3) { matrixDifferent = true; break; } } } if (!matrixDifferent) { return; } vtkNew hmdToWorldTransform; hmdToWorldTransform->SetMatrix(matrix); double translation[3] = { 0.0 }; hmdToWorldTransform->GetPosition(translation); this->PhysicalTranslation[0] = (-1.0) * translation[0]; this->PhysicalTranslation[1] = (-1.0) * translation[1]; this->PhysicalTranslation[2] = (-1.0) * translation[2]; double scale[3] = { 0.0 }; hmdToWorldTransform->GetScale(scale); this->PhysicalScale = scale[0]; this->PhysicalViewUp[0] = matrix->GetElement(0, 1); this->PhysicalViewUp[1] = matrix->GetElement(1, 1); this->PhysicalViewUp[2] = matrix->GetElement(2, 1); vtkMath::Normalize(this->PhysicalViewUp); this->PhysicalViewDirection[0] = (-1.0) * matrix->GetElement(0, 2); this->PhysicalViewDirection[1] = (-1.0) * matrix->GetElement(1, 2); this->PhysicalViewDirection[2] = (-1.0) * matrix->GetElement(2, 2); vtkMath::Normalize(this->PhysicalViewDirection); this->InvokeEvent(vtkRenderWindow::PhysicalToWorldMatrixModified); this->Modified(); } //------------------------------------------------------------------------------ void vtkRenderWindow::GetPhysicalToWorldMatrix(vtkMatrix4x4* physicalToWorldMatrix) { if (!physicalToWorldMatrix) { return; } physicalToWorldMatrix->Identity(); // construct physical to non-scaled world axes (scaling is applied later) double physicalZ_NonscaledWorld[3] = { -this->PhysicalViewDirection[0], -this->PhysicalViewDirection[1], -this->PhysicalViewDirection[2] }; double* physicalY_NonscaledWorld = this->PhysicalViewUp; double physicalX_NonscaledWorld[3] = { 0.0 }; vtkMath::Cross(physicalY_NonscaledWorld, physicalZ_NonscaledWorld, physicalX_NonscaledWorld); for (int row = 0; row < 3; ++row) { physicalToWorldMatrix->SetElement(row, 0, physicalX_NonscaledWorld[row] * this->PhysicalScale); physicalToWorldMatrix->SetElement(row, 1, physicalY_NonscaledWorld[row] * this->PhysicalScale); physicalToWorldMatrix->SetElement(row, 2, physicalZ_NonscaledWorld[row] * this->PhysicalScale); physicalToWorldMatrix->SetElement(row, 3, -this->PhysicalTranslation[row]); } } //------------------------------------------------------------------------------ bool vtkRenderWindow::GetDeviceToWorldMatrixForDevice( vtkEventDataDevice vtkNotUsed(device), vtkMatrix4x4* vtkNotUsed(deviceToWorldMatrix)) { return false; } //------------------------------------------------------------------------------ void vtkRenderWindow::SetDesiredUpdateRate(double rate) { vtkRenderer* aren; if (this->DesiredUpdateRate != rate) { vtkCollectionSimpleIterator rsit; for (this->Renderers->InitTraversal(rsit); (aren = this->Renderers->GetNextRenderer(rsit));) { aren->SetAllocatedRenderTime(1.0 / (rate * this->Renderers->GetNumberOfItems())); } this->DesiredUpdateRate = rate; this->Modified(); } } //------------------------------------------------------------------------------ void vtkRenderWindow::SetStereoType(int stereoType) { if (this->StereoType == stereoType) { return; } this->StereoType = stereoType; this->InvokeEvent(vtkCommand::WindowStereoTypeChangedEvent); this->Modified(); } //------------------------------------------------------------------------------ void vtkRenderWindow::SetCoverable(vtkTypeBool coverable) { if (coverable) { vtkWarningMacro(<< "SetCoverable(" << coverable << ") is unsupported for " << this->GetClassName()); } } //------------------------------------------------------------------------------ // // Set the variable that indicates that we want a stereo capable window // be created. This method can only be called before a window is realized. // void vtkRenderWindow::SetStereoCapableWindow(vtkTypeBool capable) { if (this->StereoCapableWindow != capable) { this->StereoCapableWindow = capable; this->Modified(); } } //------------------------------------------------------------------------------ // Turn on stereo rendering void vtkRenderWindow::SetStereoRender(vtkTypeBool stereo) { if (stereo == this->StereoRender) { return; } if (this->StereoCapableWindow || (this->StereoType != VTK_STEREO_CRYSTAL_EYES)) { this->StereoRender = stereo; this->Modified(); } else { vtkWarningMacro(<< "Adjusting stereo mode on a window that does not " << "support stereo type " << this->GetStereoTypeAsString() << " is not possible."); } } //------------------------------------------------------------------------------ // Ask each renderer owned by this RenderWindow to render its image and // synchronize this process. void vtkRenderWindow::Render() { // if we are in the middle of an abort check then return now if (this->InAbortCheck) { return; } // if we are in a render already from somewhere else abort now if (this->InRender) { return; } // if SetSize has not yet been called (from a script, possible off // screen use, other scenarios?) then call it here with reasonable // default values if (0 == this->Size[0] && 0 == this->Size[1]) { this->SetSize(300, 300); } // reset the Abort flag this->AbortRender = 0; this->InRender = 1; vtkDebugMacro(<< "Starting Render Method.\n"); this->InvokeEvent(vtkCommand::StartEvent, nullptr); this->NeverRendered = 0; if (this->Interactor && !this->Interactor->GetInitialized()) { this->Interactor->Initialize(); } this->Start(); // Ensure context exists vtkRenderTimerLog::ScopedEventLogger event; if (this->RenderTimer->GetLoggingEnabled()) { this->RenderTimer->MarkFrame(); event = this->RenderTimer->StartScopedEvent("vtkRenderWindow::Render"); } this->DoStereoRender(); this->End(); // restores original bindings this->CopyResultFrame(); // reset the buffer size without freeing any memory. this->ResultFrame->Reset(); // Stop the render timer before invoking the EndEvent. event.Stop(); this->InRender = 0; this->InvokeEvent(vtkCommand::EndEvent, nullptr); } //------------------------------------------------------------------------------ // Handle rendering the two different views for stereo rendering. void vtkRenderWindow::DoStereoRender() { vtkCollectionSimpleIterator rsit; this->StereoUpdate(); if (!this->StereoRender || (this->StereoType != VTK_STEREO_RIGHT)) { // render the left eye vtkRenderer* aren; for (this->Renderers->InitTraversal(rsit); (aren = this->Renderers->GetNextRenderer(rsit));) { // Ugly piece of code - we need to know if the camera already // exists or not. If it does not yet exist, we must reset the // camera here - otherwise it will never be done (missing its // oppportunity to be reset in the Render method of the // vtkRenderer because it will already exist by that point...) if (!aren->IsActiveCameraCreated()) { aren->ResetCamera(); } aren->GetActiveCamera()->SetLeftEye(1); } this->Renderers->Render(); } if (this->StereoRender) { this->StereoMidpoint(); if (this->StereoType != VTK_STEREO_LEFT) { // render the right eye vtkRenderer* aren; for (this->Renderers->InitTraversal(rsit); (aren = this->Renderers->GetNextRenderer(rsit));) { // Duplicate the ugly code here too. Of course, most // times the left eye will have been rendered before // the right eye, but it is possible that the user sets // everything up and renders just the right eye - so we // need this check here too. if (!aren->IsActiveCameraCreated()) { aren->ResetCamera(); } if (this->StereoType != VTK_STEREO_FAKE) { aren->GetActiveCamera()->SetLeftEye(0); } } this->Renderers->Render(); } this->StereoRenderComplete(); } } //------------------------------------------------------------------------------ // Add a renderer to the list of renderers. void vtkRenderWindow::AddRenderer(vtkRenderer* ren) { if (this->HasRenderer(ren)) { return; } // we are its parent ren->SetRenderWindow(this); this->Renderers->AddItem(ren); vtkRenderer* aren; vtkCollectionSimpleIterator rsit; for (this->Renderers->InitTraversal(rsit); (aren = this->Renderers->GetNextRenderer(rsit));) { aren->SetAllocatedRenderTime( 1.0 / (this->DesiredUpdateRate * this->Renderers->GetNumberOfItems())); } } //------------------------------------------------------------------------------ // Remove a renderer from the list of renderers. void vtkRenderWindow::RemoveRenderer(vtkRenderer* ren) { // we are its parent if (ren->GetRenderWindow() == this) { ren->ReleaseGraphicsResources(this); ren->SetRenderWindow(nullptr); } this->Renderers->RemoveItem(ren); } vtkTypeBool vtkRenderWindow::HasRenderer(vtkRenderer* ren) { return (ren && this->Renderers->IndexOfFirstOccurrence(ren) >= 0); } //------------------------------------------------------------------------------ int vtkRenderWindow::CheckAbortStatus() { if (!this->InAbortCheck) { // Only check for abort at most 5 times per second. if (vtkTimerLog::GetUniversalTime() - this->AbortCheckTime > 0.2) { this->InAbortCheck = 1; this->InvokeEvent(vtkCommand::AbortCheckEvent, nullptr); this->InAbortCheck = 0; this->AbortCheckTime = vtkTimerLog::GetUniversalTime(); } } return this->AbortRender; } //------------------------------------------------------------------------------ void vtkRenderWindow::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Borders: " << (this->Borders ? "On\n" : "Off\n"); os << indent << "Double Buffer: " << (this->DoubleBuffer ? "On\n" : "Off\n"); os << indent << "Coverable: " << (this->Coverable ? "On\n" : "Off\n"); os << indent << "Full Screen: " << (this->FullScreen ? "On\n" : "Off\n"); os << indent << "Renderers:\n"; this->Renderers->PrintSelf(os, indent.GetNextIndent()); os << indent << "Stereo Capable Window Requested: " << (this->StereoCapableWindow ? "Yes\n" : "No\n"); os << indent << "Stereo Render: " << (this->StereoRender ? "On\n" : "Off\n"); os << indent << "Point Smoothing: " << (this->PointSmoothing ? "On\n" : "Off\n"); os << indent << "Line Smoothing: " << (this->LineSmoothing ? "On\n" : "Off\n"); os << indent << "Polygon Smoothing: " << (this->PolygonSmoothing ? "On\n" : "Off\n"); os << indent << "Abort Render: " << this->AbortRender << "\n"; os << indent << "Current Cursor: " << this->CurrentCursor << "\n"; os << indent << "Desired Update Rate: " << this->DesiredUpdateRate << "\n"; os << indent << "In Abort Check: " << this->InAbortCheck << "\n"; os << indent << "NeverRendered: " << this->NeverRendered << "\n"; os << indent << "Interactor: " << this->Interactor << "\n"; os << indent << "Swap Buffers: " << (this->SwapBuffers ? "On\n" : "Off\n"); os << indent << "Stereo Type: " << this->GetStereoTypeAsString() << "\n"; os << indent << "Number of Layers: " << this->NumberOfLayers << "\n"; os << indent << "AlphaBitPlanes: " << (this->AlphaBitPlanes ? "On" : "Off") << endl; os << indent << "UseSRGBColorSpace: " << (this->UseSRGBColorSpace ? "On" : "Off") << endl; os << indent << "AnaglyphColorSaturation: " << this->AnaglyphColorSaturation << "\n"; os << indent << "AnaglyphColorMask: " << this->AnaglyphColorMask[0] << " , " << this->AnaglyphColorMask[1] << "\n"; os << indent << "MultiSamples: " << this->MultiSamples << "\n"; os << indent << "StencilCapable: " << (this->StencilCapable ? "True" : "False") << endl; os << indent << "PhysicalViewDirection: (" << this->PhysicalViewDirection[0] << ", " << this->PhysicalViewDirection[1] << ", " << this->PhysicalViewDirection[2] << ")\n"; os << indent << "PhysicalViewUp: (" << this->PhysicalViewUp[0] << ", " << this->PhysicalViewUp[1] << ", " << this->PhysicalViewUp[2] << ")\n"; os << indent << "PhysicalTranslation: (" << this->PhysicalTranslation[0] << ", " << this->PhysicalTranslation[1] << ", " << this->PhysicalTranslation[2] << ")\n"; os << indent << "PhysicalScale: " << this->PhysicalScale << "\n"; } //------------------------------------------------------------------------------ // Update the system, if needed, due to stereo rendering. For some stereo // methods, subclasses might need to switch some hardware settings here. void vtkRenderWindow::StereoUpdate() {} //------------------------------------------------------------------------------ // Intermediate method performs operations required between the rendering // of the left and right eye. void vtkRenderWindow::StereoMidpoint() { vtkRenderer* aren; /* For IceT stereo */ for (Renderers->InitTraversal(); (aren = Renderers->GetNextItem());) { aren->StereoMidpoint(); } if ((this->StereoType == VTK_STEREO_RED_BLUE) || (this->StereoType == VTK_STEREO_INTERLACED) || (this->StereoType == VTK_STEREO_DRESDEN) || (this->StereoType == VTK_STEREO_ANAGLYPH) || (this->StereoType == VTK_STEREO_CHECKERBOARD) || (this->StereoType == VTK_STEREO_SPLITVIEWPORT_HORIZONTAL)) { int* size; // get the size size = this->GetSize(); // get the data this->GetPixelData(0, 0, size[0] - 1, size[1] - 1, 0, this->StereoBuffer); } } //------------------------------------------------------------------------------ // Handles work required once both views have been rendered when using // stereo rendering. void vtkRenderWindow::StereoRenderComplete() { const int* size = this->GetSize(); switch (this->StereoType) { case VTK_STEREO_RED_BLUE: this->GetPixelData(0, 0, size[0] - 1, size[1] - 1, 0, this->ResultFrame); this->StereoCompositor->RedBlue(this->StereoBuffer, this->ResultFrame); std::swap(this->StereoBuffer, this->ResultFrame); break; case VTK_STEREO_ANAGLYPH: this->GetPixelData(0, 0, size[0] - 1, size[1] - 1, 0, this->ResultFrame); this->StereoCompositor->Anaglyph(this->StereoBuffer, this->ResultFrame, this->AnaglyphColorSaturation, this->AnaglyphColorMask); std::swap(this->StereoBuffer, this->ResultFrame); break; case VTK_STEREO_INTERLACED: this->GetPixelData(0, 0, size[0] - 1, size[1] - 1, 0, this->ResultFrame); this->StereoCompositor->Interlaced(this->StereoBuffer, this->ResultFrame, size); std::swap(this->StereoBuffer, this->ResultFrame); break; case VTK_STEREO_DRESDEN: this->GetPixelData(0, 0, size[0] - 1, size[1] - 1, 0, this->ResultFrame); this->StereoCompositor->Dresden(this->StereoBuffer, this->ResultFrame, size); std::swap(this->StereoBuffer, this->ResultFrame); break; case VTK_STEREO_CHECKERBOARD: this->GetPixelData(0, 0, size[0] - 1, size[1] - 1, 0, this->ResultFrame); this->StereoCompositor->Checkerboard(this->StereoBuffer, this->ResultFrame, size); std::swap(this->StereoBuffer, this->ResultFrame); break; case VTK_STEREO_SPLITVIEWPORT_HORIZONTAL: this->GetPixelData(0, 0, size[0] - 1, size[1] - 1, 0, this->ResultFrame); this->StereoCompositor->SplitViewportHorizontal(this->StereoBuffer, this->ResultFrame, size); std::swap(this->StereoBuffer, this->ResultFrame); break; } this->StereoBuffer->Reset(); } //------------------------------------------------------------------------------ void vtkRenderWindow::CopyResultFrame() { if (this->ResultFrame->GetNumberOfTuples() > 0) { int* size; // get the size size = this->GetSize(); assert(this->ResultFrame->GetNumberOfTuples() == size[0] * size[1]); this->SetPixelData(0, 0, size[0] - 1, size[1] - 1, this->ResultFrame, 0); } // Just before we swap buffers (in case of double buffering), we fire the // RenderEvent marking that a render call has concluded successfully. We // separate this from EndEvent since some applications may want to put some // more elements on the "draw-buffer" before calling the rendering complete. // This event gives them that opportunity. this->InvokeEvent(vtkCommand::RenderEvent); this->Frame(); } //------------------------------------------------------------------------------ // treat renderWindow and interactor as one object. // it might be easier if the GetReference count method were redefined. void vtkRenderWindow::UnRegister(vtkObjectBase* o) { if (this->Interactor && this->Interactor->GetRenderWindow() == this && this->Interactor != o) { if (this->GetReferenceCount() + this->Interactor->GetReferenceCount() == 3) { this->vtkObject::UnRegister(o); vtkRenderWindowInteractor* tmp = this->Interactor; tmp->Register(nullptr); this->Interactor->SetRenderWindow(nullptr); tmp->UnRegister(nullptr); return; } } this->vtkObject::UnRegister(o); } //------------------------------------------------------------------------------ const char* vtkRenderWindow::GetRenderLibrary() { return vtkGraphicsFactory::GetRenderLibrary(); } //------------------------------------------------------------------------------ const char* vtkRenderWindow::GetRenderingBackend() { return "Unknown"; } //------------------------------------------------------------------------------ void vtkRenderWindow::CaptureGL2PSSpecialProps(vtkCollection* result) { if (result == nullptr) { vtkErrorMacro(<< "CaptureGL2PSSpecialProps was passed a nullptr pointer."); return; } result->RemoveAllItems(); if (this->CapturingGL2PSSpecialProps) { vtkDebugMacro(<< "Called recursively."); return; } this->CapturingGL2PSSpecialProps = 1; vtkRenderer* ren; for (Renderers->InitTraversal(); (ren = Renderers->GetNextItem());) { vtkNew props; result->AddItem(props); ren->SetGL2PSSpecialPropCollection(props); } this->Render(); for (Renderers->InitTraversal(); (ren = Renderers->GetNextItem());) { ren->SetGL2PSSpecialPropCollection(nullptr); } this->CapturingGL2PSSpecialProps = 0; } // Description: Return the stereo type as a character string. // when this method was inlined, static linking on BlueGene failed // (symbol referenced which is defined in discarded section) const char* vtkRenderWindow::GetStereoTypeAsString() { return vtkRenderWindow::GetStereoTypeAsString(this->StereoType); } const char* vtkRenderWindow::GetStereoTypeAsString(int type) { switch (type) { case VTK_STEREO_CRYSTAL_EYES: return "CrystalEyes"; case VTK_STEREO_RED_BLUE: return "RedBlue"; case VTK_STEREO_LEFT: return "Left"; case VTK_STEREO_RIGHT: return "Right"; case VTK_STEREO_DRESDEN: return "DresdenDisplay"; case VTK_STEREO_ANAGLYPH: return "Anaglyph"; case VTK_STEREO_CHECKERBOARD: return "Checkerboard"; case VTK_STEREO_SPLITVIEWPORT_HORIZONTAL: return "SplitViewportHorizontal"; case VTK_STEREO_FAKE: return "Fake"; case VTK_STEREO_EMULATE: return "Emulate"; case VTK_STEREO_ZSPACE_INSPIRE: return "Inspire"; default: return ""; } } VTK_ABI_NAMESPACE_END