// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkActor.h" #include "vtkArrowSource.h" #include "vtkCompositePolyDataMapper.h" #include "vtkConeSource.h" #include "vtkCubeSource.h" #include "vtkCylinderSource.h" #include "vtkDiskSource.h" #include "vtkPartitionedDataSetCollectionSource.h" #include "vtkPlatonicSolidSource.h" #include "vtkRegularPolygonSource.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkSmartPointer.h" #include "vtkSphereSource.h" #include "vtkStringFormatter.h" #include "vtkStringScanner.h" #include "vtkSuperquadricSource.h" #include "vtkWebAssemblyOpenGLRenderWindow.h" #include "vtkWebAssemblyRenderWindowInteractor.h" #include #include #include #include #include #include namespace { std::vector> interactors; } int main(int argc, char* argv[]) { vtkRenderWindowInteractor::InteractorManagesTheEventLoop = false; if (argc < 2) { std::cerr << "Usage: MultipleCanvases \n"; } int numCanvases; VTK_FROM_CHARS_IF_ERROR_RETURN(argv[1], numCanvases, EXIT_FAILURE); std::array, 10> sources; std::size_t i = 0; sources[i++] = { vtk::TakeSmartPointer(vtkArrowSource::New()) }; sources[i++] = { vtk::TakeSmartPointer(vtkConeSource::New()) }; sources[i++] = { vtk::TakeSmartPointer(vtkCubeSource::New()) }; sources[i++] = { vtk::TakeSmartPointer(vtkCylinderSource::New()) }; sources[i++] = { vtk::TakeSmartPointer(vtkDiskSource::New()) }; sources[i++] = { vtk::TakeSmartPointer(vtkPartitionedDataSetCollectionSource::New()) }; sources[i++] = { vtk::TakeSmartPointer(vtkPlatonicSolidSource::New()) }; sources[i++] = { vtk::TakeSmartPointer(vtkRegularPolygonSource::New()) }; sources[i++] = { vtk::TakeSmartPointer(vtkSphereSource::New()) }; sources[i++] = { vtk::TakeSmartPointer(vtkSuperquadricSource::New()) }; for (int iCanvas = 0; iCanvas < numCanvases; ++iCanvas) { const std::string canvasId = "canvas" + vtk::to_string(iCanvas); const std::string canvasSelector = "#" + canvasId; vtkNew renderWindow; vtkNew interactor; vtkNew renderer; vtkNew actor; vtkNew mapper; auto& source = sources[iCanvas % sources.size()]; mapper->SetInputConnection(source->GetOutputPort()); mapper->ScalarVisibilityOff(); actor->SetMapper(mapper); renderer->AddActor(actor); if (auto* wasmInteractor = vtkWebAssemblyRenderWindowInteractor::SafeDownCast(interactor)) { wasmInteractor->SetCanvasSelector(canvasSelector.c_str()); } if (auto* wasmGLWindow = vtkWebAssemblyOpenGLRenderWindow::SafeDownCast(renderWindow)) { wasmGLWindow->SetCanvasSelector(canvasSelector.c_str()); } renderer->SetBackground(0.3, 0.3, 0.3); renderWindow->AddRenderer(renderer); interactor->SetRenderWindow(renderWindow); interactors.emplace_back(interactor); // clang-format off #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" MAIN_THREAD_EM_ASM({addCanvas($0, $1, $2); }, canvasId.c_str(), source->GetClassName(), iCanvas); #pragma clang diagnostic pop // clang-format on renderer->ResetCamera(); renderWindow->Render(); } return 0; } extern "C" { EMSCRIPTEN_KEEPALIVE void startEventLoop(int iCanvas) { if (static_cast(iCanvas) < interactors.size()) { interactors[iCanvas]->Start(); } } EMSCRIPTEN_KEEPALIVE void updateSize(int iCanvas, int width, int height) { if (static_cast(iCanvas) < interactors.size()) { interactors[iCanvas]->UpdateSize(width, height); } } EMSCRIPTEN_KEEPALIVE void render(int iCanvas, int width, int height) { if (static_cast(iCanvas) < interactors.size()) { interactors[iCanvas]->GetRenderWindow()->Render(); } } EMSCRIPTEN_KEEPALIVE void stopEventLoop(int iCanvas) { if (static_cast(iCanvas) < interactors.size()) { interactors[iCanvas]->TerminateApp(); } } }