Skip to content
Snippets Groups Projects
Commit 4b0b3b31 authored by Jaswant Panchumarti (Kitware)'s avatar Jaswant Panchumarti (Kitware)
Browse files

wasm-opengl: replace SDL2 with emscripten webgl API

- this API works in wasm64 and web-workers
- the version of sdl2 ported by emscripten did not.
- deprecates vtkSDL2OpenGLRenderWindow for 9.4
- include vtkOpenGLOptions at the top of root CMakeLists.txt
  so that vtk_module_scan sees VTK_OPENGL_USE_GLES
parent 540986cd
No related branches found
No related tags found
No related merge requests found
......@@ -27,6 +27,7 @@ set(default_use_sdl2 OFF)
if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
set(default_use_sdl2 ON)
endif()
# VTK_DEPRECATED_IN_9_4_0() Remove option when vtkSDL2OpenGLRenderWindow and vtkSDL2WebGPURenderWindow are removed.
option(VTK_USE_SDL2 "Add SDL2 classes to VTK" "${default_use_sdl2}")
mark_as_advanced(VTK_USE_SDL2)
......@@ -101,6 +102,11 @@ endif ()
if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
set(vtk_can_do_headless FALSE)
# VTK_DEPRECATED_IN_9_4_0() Unconditionally set both variables to TRUE after VTK_USE_SDL2 is removed.
if (NOT VTK_USE_SDL2)
set(vtk_can_do_onscreen TRUE)
set(vtk_can_do_offscreen TRUE)
endif ()
endif ()
if (NOT vtk_can_do_onscreen AND NOT vtk_can_do_offscreen)
......
......@@ -91,6 +91,7 @@ include(vtkMobileDevices)
include(vtkWrapSettings)
include(vtkCrossCompiling)
include(vtkObjectFactory)
include(vtkOpenGLOptions)
option(VTK_RELOCATABLE_INSTALL "Do not embed hard-coded paths into the install" ON)
mark_as_advanced(VTK_RELOCATABLE_INSTALL)
......
## vtkWebAssemblyOpenGLRenderWindow: Support wasm64 and web workers
`vtkWebAssemblyOpenGLRenderWindow` is a new class that now uses Emscripten HTML5 and WebGL API for OpenGL context creation instead of SDL2. This update ensures smoother operation in wasm64 and web worker environments.
What this means: You can now completely offload VTK OpenGL rendering within a web worker inside a browser.
The new `vtkWebAssemblyOpenGLRenderWindow` is now the default factory override
of `vtkRenderWindow` for OpenGL in webassembly. It is meant to replace the `vtkSDL2OpenGLRenderWindow`, which will soon be deprecated.
......@@ -338,11 +338,20 @@ elseif (ANDROID)
OVERRIDE vtkEGLRenderWindow)
set(has_vtkRenderWindow_override 1)
include_directories("${CMAKE_ANDROID_NDK}/sources/android/native_app_glue")
elseif (EMSCRIPTEN)
elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
# Add some custom overrides
vtk_object_factory_declare(
BASE vtkRenderWindow
OVERRIDE vtkSDL2OpenGLRenderWindow)
# VTK_DEPRECATED_IN_9_4_0() Remove when vtkSDL2OpenGLRenderWindow is removed.
if (VTK_USE_SDL2)
vtk_object_factory_declare(
BASE vtkRenderWindow
OVERRIDE vtkSDL2OpenGLRenderWindow)
list(APPEND classes vtkSDL2OpenGLRenderWindow)
else ()
vtk_object_factory_declare(
BASE vtkRenderWindow
OVERRIDE vtkWebAssemblyOpenGLRenderWindow)
list(APPEND classes vtkWebAssemblyOpenGLRenderWindow)
endif ()
set(has_vtkRenderWindow_override 1)
elseif (APPLE_IOS)
# Add some custom overrides
......@@ -403,10 +412,6 @@ configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/vtkRenderingOpenGLConfigure.h.in"
"${CMAKE_CURRENT_BINARY_DIR}/vtkRenderingOpenGLConfigure.h")
if (VTK_USE_SDL2)
list(APPEND classes vtkSDL2OpenGLRenderWindow)
endif ()
vtk_module_add_module(VTK::RenderingOpenGL2
CLASSES ${classes}
PRIVATE_CLASSES ${private_classes}
......@@ -415,8 +420,9 @@ vtk_module_add_module(VTK::RenderingOpenGL2
NOWRAP_HEADERS ${nowrap_headers}
PRIVATE_HEADERS ${private_headers} ${vtk_object_factory_header})
if (VTK_USE_SDL2)
if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
# VTK_DEPRECATED_IN_9_4_0() Remove when vtkSDL2OpenGLRenderWindow is removed.
if (VTK_USE_SDL2)
# The -sUSE_SDL=2 flag will inform emcc driver to add include paths.
# PUBLIC because vtkSDL2OpenGLRenderWindow.h includes SDL2.h
vtk_module_compile_options(VTK::RenderingUI
......@@ -425,13 +431,15 @@ if (VTK_USE_SDL2)
vtk_module_link_options(VTK::RenderingUI
PUBLIC
"-sUSE_SDL=2")
else()
vtk_module_find_package(PACKAGE SDL2)
# PUBLIC because vtkSDL2OpenGLRenderWindow.h includes SDL2.h
vtk_module_link(VTK::RenderingUI
PUBLIC
SDL2::SDL2)
endif ()
elseif (VTK_USE_SDL2)
# VTK_DEPRECATED_IN_9_4_0() Remove when vtkSDL2OpenGLRenderWindow is removed.
list(APPEND classes vtkSDL2OpenGLRenderWindow)
vtk_module_find_package(PACKAGE SDL2)
# PUBLIC because vtkSDL2OpenGLRenderWindow.h includes SDL2.h
vtk_module_link(VTK::RenderingUI
PUBLIC
SDL2::SDL2)
endif ()
if (VTK_USE_X)
......
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
// Hide VTK_DEPRECATED_IN_9_4_0() warnings for this class.
#define VTK_DEPRECATION_LEVEL 0
#include "vtkSDL2OpenGLRenderWindow.h"
#include "vtkCommand.h"
......
......@@ -13,6 +13,8 @@
#define vtkSDL2OpenGLRenderWindow_h
#include "vtkOpenGLRenderWindow.h"
#include "vtkDeprecation.h" // For VTK_DEPRECATED_IN_9_4_0
#include "vtkRenderingOpenGL2Module.h" // For export macro
#include "vtkWrappingHints.h" // For VTK_MARSHALAUTO
// Ignore reserved-identifier warnings from
......@@ -34,7 +36,10 @@
#include <stack> // for ivar
VTK_ABI_NAMESPACE_BEGIN
class VTKRENDERINGOPENGL2_EXPORT VTK_MARSHALAUTO vtkSDL2OpenGLRenderWindow
class VTK_DEPRECATED_IN_9_4_0(
"Please use one of the dedicated platform render window or "
"vtkWebAssemblyOpenGLRenderWindow if your application targets WebAssembly.")
VTKRENDERINGOPENGL2_EXPORT VTK_MARSHALAUTO vtkSDL2OpenGLRenderWindow
: public vtkOpenGLRenderWindow
{
public:
......
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
#include "vtkWebAssemblyOpenGLRenderWindow.h"
#include "vtkCommand.h"
#include "vtkObjectFactory.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRendererCollection.h"
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/html5_webgl.h>
#include <webgl/webgl2.h>
VTK_ABI_NAMESPACE_BEGIN
vtkStandardNewMacro(vtkWebAssemblyOpenGLRenderWindow);
//------------------------------------------------------------------------------
vtkWebAssemblyOpenGLRenderWindow::vtkWebAssemblyOpenGLRenderWindow()
: ContextId(0)
{
this->SetWindowName("Visualization Toolkit - Emscripten OpenGL #");
this->SetCanvasId("#canvas");
this->SetStencilCapable(1);
this->Position[0] = -1;
this->Position[1] = -1;
this->FrameBlitMode = BlitToCurrent;
}
//------------------------------------------------------------------------------
vtkWebAssemblyOpenGLRenderWindow::~vtkWebAssemblyOpenGLRenderWindow()
{
this->Finalize();
vtkRenderer* ren;
vtkCollectionSimpleIterator rit;
this->Renderers->InitTraversal(rit);
while ((ren = this->Renderers->GetNextRenderer(rit)))
{
ren->SetRenderWindow(nullptr);
}
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::Clean()
{
if (this->OwnContext && this->ContextId)
{
this->MakeCurrent();
this->CleanUpRenderers();
emscripten_webgl_destroy_context(this->ContextId);
}
this->ContextId = 0;
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::CleanUpRenderers()
{
// tell each of the renderers that this render window/graphics context
// is being removed (the RendererCollection is removed by vtkRenderWindow's
// destructor)
this->ReleaseGraphicsResources(this);
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::SetWindowName(const char* title)
{
this->Superclass::SetWindowName(title);
if (this->ContextId)
{
emscripten_set_window_title(title);
}
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::MakeCurrent()
{
if (this->ContextId)
{
emscripten_webgl_make_context_current(this->ContextId);
}
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::ReleaseCurrent()
{
if (this->ContextId)
{
emscripten_webgl_make_context_current(0);
}
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::PushContext()
{
auto current = emscripten_webgl_get_current_context();
this->ContextStack.push(current);
if (current != this->ContextId)
{
this->MakeCurrent();
}
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::PopContext()
{
auto current = emscripten_webgl_get_current_context();
auto target = this->ContextStack.top();
this->ContextStack.pop();
if (target != current)
{
emscripten_webgl_make_context_current(target);
}
}
//------------------------------------------------------------------------------
bool vtkWebAssemblyOpenGLRenderWindow::IsCurrent()
{
return this->ContextId != 0 && this->ContextId == emscripten_webgl_get_current_context();
}
//------------------------------------------------------------------------------
bool vtkWebAssemblyOpenGLRenderWindow::SetSwapControl(int interval)
{
if (interval < 0)
{
vtkWarningMacro("Late swap tearing currently unsupported!");
return false;
}
else if (interval == 0)
{
emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, 0);
}
else
{
emscripten_set_main_loop_timing(EM_TIMING_RAF, interval);
}
return true;
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::SetSize(int width, int height)
{
if ((this->Size[0] != width) || (this->Size[1] != height))
{
this->Size[0] = width;
this->Size[1] = height;
emscripten_set_canvas_element_size(this->CanvasId, this->Size[0], this->Size[1]);
if (this->Interactor)
{
this->Interactor->SetSize(this->Size[0], this->Size[1]);
}
this->Modified();
this->InvokeEvent(vtkCommand::WindowResizeEvent, nullptr);
}
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::Frame()
{
this->Superclass::Frame();
if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers)
{
if (emscripten_has_asyncify())
{
// give back control to browser for screen refresh */
emscripten_sleep(0);
}
}
}
//------------------------------------------------------------------------------
int vtkWebAssemblyOpenGLRenderWindow::GetColorBufferSizes(int* rgba)
{
if (rgba == nullptr)
{
return 0;
}
rgba[0] = emscripten_webgl_get_parameter_d(GL_RED_BITS);
rgba[1] = emscripten_webgl_get_parameter_d(GL_GREEN_BITS);
rgba[2] = emscripten_webgl_get_parameter_d(GL_BLUE_BITS);
rgba[3] = emscripten_webgl_get_parameter_d(GL_ALPHA_BITS);
return (rgba[0] > 0) && (rgba[1] > 0) && (rgba[2] > 0) && (rgba[3] > 0);
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::SetShowWindow(bool val)
{
this->Superclass::SetShowWindow(val);
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::CreateAWindow()
{
EmscriptenWebGLContextAttributes attrs;
emscripten_webgl_init_context_attributes(&attrs);
// request webgl2 (similar to gles 3.0)
attrs.majorVersion = 2;
// Not to be confused with the MultiSamples property on vtkRenderWindow.
// This `antialias` property concerns the webgl2 context of a canvas.
// VTK renders to offscreen (in memory) multi-sampled framebuffers and resolves
// the pixels to the draw buffer when it's time to swap buffers. Consequently,
// the final blit expects that the destination framebuffer is not multi-sampled.
// If you turn this on for the canvas's webgl2 context, you will see a black screen and a warning
// in
// 1. chrome - [.WebGL-0x9fc004be900] GL_INVALID_OPERATION: Invalid operation on multisampled
// framebuffer
// 2. firefox - WebGL warning: blitFramebuffer: DRAW_FRAMEBUFFER may not have multiple samples.
attrs.antialias = 0;
// do not blend the canvas with underlying web page contents.
attrs.alpha = 0;
attrs.depth = true;
attrs.stencil = this->StencilCapable;
const auto result = emscripten_webgl_create_context(this->CanvasId, &attrs);
if (result <= 0)
{
vtkErrorMacro("Error (" << result << ") initializing WebGL2.");
return;
}
if (emscripten_webgl_make_context_current(result) != EMSCRIPTEN_RESULT_SUCCESS)
{
emscripten_webgl_destroy_context(result);
return;
}
this->ContextId = result;
int width = ((this->Size[0] > 0) ? this->Size[0] : 300);
int height = ((this->Size[1] > 0) ? this->Size[1] : 300);
this->SetSize(width, height);
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::Initialize()
{
if (!this->ContextId)
{
this->CreateAWindow();
}
if (!this->ContextId)
{
vtkErrorMacro("Failed to create Emscripten opengl context");
return;
}
this->OpenGLInit();
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::Finalize()
{
this->DestroyWindow();
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::DestroyWindow()
{
this->Clean();
}
//------------------------------------------------------------------------------
int* vtkWebAssemblyOpenGLRenderWindow::GetScreenSize(void)
{
emscripten_get_screen_size(&this->ScreenSize[0], &this->ScreenSize[1]);
return this->ScreenSize;
}
//------------------------------------------------------------------------------
int* vtkWebAssemblyOpenGLRenderWindow::GetPosition(void)
{
return this->Position;
}
namespace
{
//------------------------------------------------------------------------------
EM_BOOL HandleCanvasResize(
int vtkNotUsed(eventType), const void* vtkNotUsed(reserved), void* userData)
{
// this is used during fullscreen changes
auto window = reinterpret_cast<vtkWebAssemblyOpenGLRenderWindow*>(userData);
int screenSize[2];
emscripten_get_screen_size(&screenSize[0], &screenSize[1]);
window->SetSize(screenSize[0], screenSize[1]);
return 0;
}
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::SetFullScreen(vtkTypeBool arg)
{
if (this->FullScreen == arg)
{
return;
}
if (!this->Mapped)
{
return;
}
// set the mode
this->FullScreen = arg;
float dpr = emscripten_get_device_pixel_ratio();
int result = -1;
if (this->FullScreen)
{
EmscriptenFullscreenStrategy strategy;
strategy.scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH;
if (dpr != 1.0f)
{
strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF;
}
else
{
strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
}
strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
strategy.canvasResizedCallback = ::HandleCanvasResize;
strategy.canvasResizedCallbackUserData = this;
result = emscripten_request_fullscreen_strategy(this->CanvasId, 1, &strategy);
}
else
{
result = emscripten_exit_fullscreen();
}
if ((result != EMSCRIPTEN_RESULT_SUCCESS) && (result == EMSCRIPTEN_RESULT_DEFERRED))
{
vtkErrorMacro(<< "Failed to request fullscreen");
return;
}
this->Modified();
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "ContextId: " << this->ContextId << "\n";
}
namespace
{
void setCursorVisibility(bool visible)
{
// clang-format off
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
MAIN_THREAD_EM_ASM({if (Module['canvas']) { Module['canvas'].style['cursor'] = $0 ? 'default' : 'none'; }}, visible);
#pragma clang diagnostic pop
// clang-format on
}
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::HideCursor()
{
::setCursorVisibility(false);
}
//------------------------------------------------------------------------------
void vtkWebAssemblyOpenGLRenderWindow::ShowCursor()
{
::setCursorVisibility(true);
}
VTK_ABI_NAMESPACE_END
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
/**
* @class vtkWebAssemblyOpenGL2RenderWindow
* @brief OpenGL rendering window
*
* vtkWebAssemblyOpenGL2RenderWindow is a concrete implementation of the abstract
* class vtkRenderWindow.
*/
#ifndef vtkWebAssemblyOpenGLRenderWindow_h
#define vtkWebAssemblyOpenGLRenderWindow_h
#include "vtkOpenGLRenderWindow.h"
#include "vtkRenderingOpenGL2Module.h" // For export macro
#include "vtkWrappingHints.h" // For VTK_MARSHALAUTO
#include <stack> // for ivar
VTK_ABI_NAMESPACE_BEGIN
class VTKRENDERINGOPENGL2_EXPORT VTK_MARSHALAUTO vtkWebAssemblyOpenGLRenderWindow
: public vtkOpenGLRenderWindow
{
public:
static vtkWebAssemblyOpenGLRenderWindow* New();
vtkTypeMacro(vtkWebAssemblyOpenGLRenderWindow, vtkOpenGLRenderWindow);
void PrintSelf(ostream& os, vtkIndent indent) override;
/**
* Initialize the rendering window. This will setup all system-specific
* resources. This method and Finalize() must be symmetric and it
* should be possible to call them multiple times, even changing WindowId
* in-between. This is what WindowRemap does.
*/
void Initialize() override;
/**
* Finalize the rendering window. This will shutdown all system-specific
* resources. After having called this, it should be possible to destroy
* a window that was used for a SetWindowId() call without any ill effects.
*/
void Finalize() override;
/**
* Change the window to fill the entire screen.
*/
void SetFullScreen(vtkTypeBool) override;
/**
* Show or not Show the window
*/
void SetShowWindow(bool val) override;
///@{
/**
* Set the size of the window in pixels.
*/
void SetSize(int, int) override;
void SetSize(int a[2]) override { vtkOpenGLRenderWindow::SetSize(a); }
///@}
///@{
/**
* Set the position of the window.
*/
void SetPosition(int x, int y) override { vtkOpenGLRenderWindow::SetPosition(x, y); }
void SetPosition(int a[2]) override { vtkOpenGLRenderWindow::SetPosition(a); }
///@}
/**
* Get the current size of the screen in pixels.
*/
int* GetScreenSize() VTK_SIZEHINT(2) override;
/**
* Get the position in screen coordinates of the window.
*/
int* GetPosition() VTK_SIZEHINT(2) override;
/**
* Set the name of the window. This appears at the top of the window
* normally.
*/
void SetWindowName(const char*) override;
void* GetGenericDisplayId() override { return (void*)this->ContextId; }
void* GetGenericWindowId() override { return (void*)this->ContextId; }
void* GetGenericDrawable() override { return (void*)this->ContextId; }
/**
* Make this windows OpenGL context the current context.
*/
void MakeCurrent() override;
/**
* Release the current context.
*/
void ReleaseCurrent() override;
/**
* Tells if this window is the current OpenGL context for the calling thread.
*/
bool IsCurrent() override;
/**
* Clean up device contexts, rendering contexts, etc.
*/
void Clean();
/**
* A termination method performed at the end of the rendering process
* to do things like swapping buffers (if necessary) or similar actions.
*/
void Frame() override;
///@{
/**
* Ability to push and pop this window's context
* as the current context. The idea being to
* if needed make this window's context current
* and when done releasing resources restore
* the prior context
*/
void PushContext() override;
void PopContext() override;
///@}
/**
* Set the number of vertical syncs required between frames.
* A value of 0 means swap buffers as quickly as possible
* regardless of the vertical refresh. A value of 1 means swap
* buffers in sync with the vertical refresh to eliminate tearing.
* A value of -1 means use a value of 1 unless we missed a frame
* in which case swap immediately. Returns true if the call
* succeeded.
*/
bool SetSwapControl(int i) override;
/**
* Get the size of the color buffer.
* Returns 0 if not able to determine otherwise sets R G B and A into buffer.
*/
int GetColorBufferSizes(int* rgba) override;
///@{
/**
* Hide or Show the mouse cursor, it is nice to be able to hide the
* default cursor if you want VTK to display a 3D cursor instead.
*/
void HideCursor() override;
void ShowCursor() override;
///@}
/**
* Specify the selector of the canvas element in the DOM.
*/
vtkGetStringMacro(CanvasId);
vtkSetStringMacro(CanvasId);
protected:
vtkWebAssemblyOpenGLRenderWindow();
~vtkWebAssemblyOpenGLRenderWindow() override;
unsigned long ContextId;
std::stack<unsigned long> ContextStack;
char* CanvasId = nullptr;
void CleanUpRenderers();
void CreateAWindow() override;
void DestroyWindow() override;
private:
vtkWebAssemblyOpenGLRenderWindow(const vtkWebAssemblyOpenGLRenderWindow&) = delete;
void operator=(const vtkWebAssemblyOpenGLRenderWindow&) = delete;
};
VTK_ABI_NAMESPACE_END
#endif
......@@ -207,6 +207,7 @@ Rendering/OpenGL2/vtkOpenGLRenderWindow.h
Rendering/OpenGL2/vtkOpenGLShaderProperty.h
Rendering/OpenGL2/vtkOSOpenGLRenderWindow.h
Rendering/OpenGL2/vtkSDL2OpenGLRenderWindow.h
Rendering/OpenGL2/vtkWebAssemblyOpenGLRenderWindow.h
Rendering/OpenGL2/vtkWin32OpenGLRenderWindow.h
Rendering/OpenGL2/vtkXOpenGLRenderWindow.h
Rendering/UI/vtkCocoaRenderWindowInteractor.h
......
......@@ -637,7 +637,10 @@ Interaction/Widgets/vtkWidgetEventTranslator.h
Interaction/Widgets/vtkWidgetSet.h
Interaction/Widgets/vtkXYPlotRepresentation.h
Interaction/Widgets/vtkXYPlotWidget.h
Rendering/Annotation/vtkArcGridActorPrivate.h
Rendering/Annotation/vtkAxisGridActorPrivate.h
Rendering/Annotation/vtkPolarAxesActor2D.h
Rendering/Annotation/vtkRadialGridActor2D.h
Rendering/Annotation/vtkScalarBarActorInternal.h
Rendering/Core/vtkAbstractHyperTreeGridMapper.h
Rendering/Core/vtkAbstractInteractionDevice.h
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment