From: Anthony Geay Date: Thu, 6 Apr 2023 15:41:09 +0000 (+0200) Subject: Successful mix PV3D viewer and pqMultiTabWidget of ParaViS module X-Git-Tag: V9_11_0a1~3 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=1af70ad9df281f2753426a0b9d72b6b518494e8c;p=modules%2Fparavis.git Successful mix PV3D viewer and pqMultiTabWidget of ParaViS module Custom CADRepresentation for selection into PV3D viewer --- diff --git a/src/PVGUI/PVGUI_Module.cxx b/src/PVGUI/PVGUI_Module.cxx index 7ab53ad5..209d0b30 100644 --- a/src/PVGUI/PVGUI_Module.cxx +++ b/src/PVGUI/PVGUI_Module.cxx @@ -83,7 +83,7 @@ #include // Paraview includes -#include // for symbol PARAVIEW_VERSION +#include // for symbol PARAVIEW_VERSION #include #include #include @@ -257,7 +257,7 @@ void PVGUI_Module::initialize( CAM_Application* app ) // Initialize ParaView client and associated behaviors // and connect to externally launched pvserver - PVViewer_Core::ParaviewInitApp(aDesktop); + PVViewer_Core::ParaviewInitApp(); // Clear old copies of embedded macros files //QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() ); diff --git a/src/Plugins/CADRepresentation/CMakeLists.txt b/src/Plugins/CADRepresentation/CMakeLists.txt new file mode 100644 index 00000000..efd2ecdc --- /dev/null +++ b/src/Plugins/CADRepresentation/CMakeLists.txt @@ -0,0 +1,54 @@ +# Copyright (C) 2023 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +cmake_minimum_required(VERSION 3.8) +project(CADRepresentations) + +find_package(ParaView REQUIRED) + +if (NOT PARAVIEW_USE_QT) + message(ERROR + ": Please make sure ParaView has been built with PARAVIEW_USE_QT enabled.") + return () +endif() + +include(GNUInstallDirs) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") + +option(BUILD_SHARED_LIBS "Build shared libraries" ON) + +paraview_plugin_scan( + PLUGIN_FILES + cadRepresentations/paraview.plugin + PROVIDES_PLUGINS plugins + ENABLE_BY_DEFAULT ON + HIDE_PLUGINS_FROM_CACHE ON) + +paraview_plugin_build( + RUNTIME_DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY_DESTINATION "${CMAKE_INSTALL_LIBDIR}" + #LIBRARY_SUBDIRECTORY "${PARAVIEW_PLUGIN_SUBDIR}" + #INSTALL_EXPORT CADViewerParaViewPlugins + CMAKE_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CADRepresentations + PLUGINS ${plugins} + TARGET CADRepresentationPlugin + #cadviewer_paraview_plugins + ) diff --git a/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/CADRepresentation.xml b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/CADRepresentation.xml new file mode 100644 index 00000000..b79338f2 --- /dev/null +++ b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/CADRepresentation.xml @@ -0,0 +1,66 @@ + + + + + CAD Representation. + + + + Set the input to the representation. Must be a vtkPolyData producer. + + + + + + + + + + Set the selection. + + + + + Set the visibility for this representation. + + + + + Set the group to show in Group Mode. + + + + + Set the opacity of the given group. + + + + + + Enable or disable the Group Mode. + + + + + + + + + diff --git a/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/CMakeLists.txt b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/CMakeLists.txt new file mode 100644 index 00000000..a5e5ce00 --- /dev/null +++ b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (C) 2023 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +set(classes + vtkCADMapper + vtkCADRepresentation) + +vtk_module_add_module(CADRepresentations + FORCE_STATIC + CLASSES ${classes}) + +paraview_add_server_manager_xmls( + XMLS CADRepresentation.xml) diff --git a/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtk.module b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtk.module new file mode 100644 index 00000000..515f266e --- /dev/null +++ b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtk.module @@ -0,0 +1,9 @@ +NAME + CADRepresentations +DEPENDS + ParaView::RemotingViews + VTK::RenderingOpenGL2 + VTK::CommonDataModel + VTK::glew +PRIVATE_DEPENDS + VTK::CommonCore diff --git a/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADMapper.cxx b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADMapper.cxx new file mode 100644 index 00000000..f0570d46 --- /dev/null +++ b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADMapper.cxx @@ -0,0 +1,452 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "vtkCADMapper.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +vtkStandardNewMacro(vtkCADMapper); + +//----------------------------------------------------------------------------- +void vtkCADMapper::SetOpacity(vtkIdType cellId, unsigned char opacity) +{ + if(this->PrimColors.empty()) + { + return; + } + + for (vtkIdType primId : this->CellToPrimMap[cellId]) + { + this->PrimColors[4 * primId + 3] = opacity; + } +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::ToggleResetColor(vtkIdType cellId) +{ + if(this->PrimColors.empty()) + { + return; + } + + const int opacity = this->GroupModeEnabled ? 0 : 255; + + // Retrieve "default" colors + unsigned char color[4]; + this->Colors->GetTypedTuple(cellId, color); + + for (vtkIdType primId : this->CellToPrimMap[cellId]) + { + this->PrimColors[4 * primId] = color[0]; + this->PrimColors[4 * primId + 1] = color[1]; + this->PrimColors[4 * primId + 2] = color[2]; + this->PrimColors[4 * primId + 3] = opacity; + } +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::ToggleSelectColor(vtkIdType cellId) +{ + if(this->PrimColors.empty()) + { + return; + } + + auto* selectionColors = + this->GroupModeEnabled ? this->GroupSelectionColor : this->SelectionColor; + + const int opacity = this->GroupModeEnabled ? this->SavedCellOpacities[cellId] : 255; + + for (vtkIdType primId : this->CellToPrimMap[cellId]) + { + this->PrimColors[4 * primId] = selectionColors[0]; + this->PrimColors[4 * primId + 1] = selectionColors[1]; + this->PrimColors[4 * primId + 2] = selectionColors[2]; + this->PrimColors[4 * primId + 3] = opacity; + } +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::TogglePreselectColor(vtkIdType cellId) +{ + if(this->PrimColors.empty()) + { + return; + } + + for (vtkIdType primId : this->CellToPrimMap[cellId]) + { + this->PrimColors[4 * primId] = this->PreselectionColor[0]; + this->PrimColors[4 * primId + 1] = this->PreselectionColor[1]; + this->PrimColors[4 * primId + 2] = this->PreselectionColor[2]; + this->PrimColors[4 * primId + 3] = 255; + } +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::ForceUpdate() +{ + this->Modified(); + this->NeedUpdate = true; +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::BuildCellTextures(vtkRenderer* ren, vtkActor* vtkNotUsed(actor), + vtkCellArray* vtkNotUsed(prims)[4], int vtkNotUsed(representation)) +{ + if (!this->NeedUpdate) + { + return; + } + + // Add the preselection + for (vtkIdType idx : + this->SelectionCache[std::make_tuple(0, 0, this->PreselectedCellId)]) + { + this->TogglePreselectColor(idx); + } + + // Fill OpenGL related buffers + if (!this->CellScalarTexture) + { + this->CellScalarTexture = vtkTextureObject::New(); + this->CellScalarBuffer = vtkOpenGLBufferObject::New(); + this->CellScalarBuffer->SetType(vtkOpenGLBufferObject::TextureBuffer); + } + this->CellScalarTexture->SetContext(static_cast(ren->GetVTKWindow())); + this->CellScalarBuffer->Upload(this->PrimColors, vtkOpenGLBufferObject::TextureBuffer); + this->CellScalarTexture->CreateTextureBuffer( + static_cast(this->PrimColors.size() / 4), 4, VTK_UNSIGNED_CHAR, + this->CellScalarBuffer); + + // Reset preselection + for (vtkIdType idx : + this->SelectionCache[std::make_tuple(0, 0, this->PreselectedCellId)]) + { + this->ToggleResetColor(idx); + } + + this->NeedUpdate = false; +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::BeginSelect() +{ + this->Selecting = true; +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::EndSelect() +{ + this->Selecting = false; +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::CreateGroup() +{ + this->SavedGroups.emplace_back(std::make_pair(this->SelectedIds, this->CurrentArrayName)); + this->SavedGroupVisibilities.emplace_back(false); + this->ResetSelection(); +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::SetGroupVisibility(int groupIdx, bool visibility) +{ + if(!this->GroupModeEnabled) + { + return; + } + + // Reconstruct the cache if needed (if a different array for selection by value is choosen) + this->BuildSelectionCache(this->SavedGroups[groupIdx].second.c_str(), 0, this->CurrentInput); + + // Save the group visibility + this->SavedGroupVisibilities[groupIdx] = visibility; + + // Show the selected group + for (vtkIdType id : this->SavedGroups[groupIdx].first) + { + for (vtkIdType idx : this->SelectionCache[std::make_tuple(0, 0, id)]) + { + if (visibility) + { + this->ToggleSelectColor(idx); + } + else + { + this->ToggleResetColor(idx); + } + } + this->SelectedIds.emplace(id); + } + this->ForceUpdate(); +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::SetGroupOpacity(int groupIdx, unsigned char opacity) +{ + if(!this->GroupModeEnabled) + { + return; + } + + // Reconstruct the cache if needed (if a different array for selection by value is choosen) + this->BuildSelectionCache(this->SavedGroups[groupIdx].second.c_str(), 0, this->CurrentInput); + + // Save the opacity of the selected group and update it directly if currently visible + for (vtkIdType id : this->SavedGroups[groupIdx].first) + { + for (vtkIdType idx : this->SelectionCache[std::make_tuple(0, 0, id)]) + { + this->SavedCellOpacities[idx] = opacity; + if(this->SavedGroupVisibilities[groupIdx]) + { + this->SetOpacity(idx, opacity); + } + } + } + this->ForceUpdate(); +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::SetGroupModeEnabled(bool enabled) +{ + this->GroupModeEnabled = enabled; + + // Set the group mode colors and opacity and clear the selections + this->InitializePrimColors(); + this->SelectedIds.clear(); + this->PreselectedCellId = -1; + + // Show all visible groups + for (vtkIdType groupId = 0; groupId < this->SavedGroups.size(); groupId++) + { + if (this->SavedGroupVisibilities[groupId]) + { + this->SetGroupVisibility(groupId, true); + } + } + + this->ForceUpdate(); +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::ResetSelection() +{ + for (vtkIdType id : this->SelectedIds) + { + for (vtkIdType idx : this->SelectionCache[std::make_tuple(0, 0, id)]) + { + this->ToggleResetColor(idx); + } + } + + this->SelectedIds.clear(); + this->PreselectedCellId = -1; + this->ForceUpdate(); +} + +//----------------------------------------------------------------------------- +void vtkCADMapper::Initialize() +{ + vtkPolyData* input = vtkPolyData::SafeDownCast(this->GetInput()); + if(!input) + { + vtkErrorMacro("Unable to retrieve input polydata."); + return; + } + + vtkCellArray* prims[4]; + + prims[0] = input->GetVerts(); + prims[1] = input->GetLines(); + prims[2] = input->GetPolys(); + prims[3] = input->GetStrips(); + + vtkIdType nbVerts = input->GetNumberOfVerts(); + vtkIdType nbLines = input->GetNumberOfLines(); + vtkIdType nbPolys = input->GetNumberOfPolys(); + + // Store the mapping from OpenGL primitives to VTK cells + this->CellCellMap->BuildCellSupportArrays(prims, VTK_SURFACE, input->GetPoints()); + + // Create the mapping from VTK cells to OpenGL primitives (inverse of CellCellMap) + this->CellToPrimMap.clear(); + this->CellToPrimMap.resize(nbVerts + nbLines + nbPolys); + for (auto& v : this->CellToPrimMap) + { + // heuristic : for performances, we assume that we will have at most 10 primitives per cell + // it's just a reserve, the algorithm will still works if there is more primitives + v.reserve(10); + } + + for (size_t i = 0; i < this->CellCellMap->GetSize(); i++) + { + this->CellToPrimMap[this->CellCellMap->GetValue(i)].push_back(i); + } + + // Reset the default colors for all VTK cells + if (vtkUnsignedCharArray::SafeDownCast(input->GetCellData()->GetArray("RGB"))) + { + input->GetCellData()->RemoveArray("RGB"); + } + + vtkNew colorArray; + colorArray->SetNumberOfComponents(3); + colorArray->SetNumberOfTuples(nbVerts + nbLines + nbPolys); + colorArray->SetName("RGB"); + + input->GetCellData()->SetScalars(colorArray); + + for (int i = 0; i < nbVerts; i++) + { + colorArray->SetTypedTuple(i, this->VertexColor); + } + + for (int i = 0; i < nbLines; i++) + { + colorArray->SetTypedTuple(nbVerts + i, this->EdgeColor); + } + + for (int i = 0; i < nbPolys; i++) + { + colorArray->SetTypedTuple(nbVerts + nbLines + i, this->FaceColor); + } + + // Initialize the primitive colors from the created color array + this->InitializePrimColors(); + + // Clear saved group visibilities + this->SavedGroupVisibilities.clear(); + + // Initialize saved cell opacities + this->SavedCellOpacities.clear(); + this->SavedCellOpacities.resize(nbVerts + nbLines + nbPolys, 255); + + // Reset texture and selection + if (this->CellScalarTexture) + { + this->CellScalarTexture->Delete(); + this->CellScalarTexture = nullptr; + } + + if (this->CellScalarBuffer) + { + this->CellScalarBuffer->Delete(); + this->CellScalarBuffer = nullptr; + } + + this->SelectedIds.clear(); + this->PreselectedCellId = -1; + this->ForceUpdate(); +} + +//---------------------------------------------------------------------------- +void vtkCADMapper::InitializePrimColors() +{ + vtkPolyData* input = vtkPolyData::SafeDownCast(this->GetInput()); + if(!input) + { + vtkErrorMacro("Unable to retrieve input polydata."); + return; + } + + vtkUnsignedCharArray* colorArray = vtkUnsignedCharArray::SafeDownCast(input->GetCellData()->GetAbstractArray("RGB")); + if(!colorArray) + { + vtkErrorMacro("Unable to retrieve the input color array."); + return; + } + + // Map the VTK cell color values to the OpenGL primitives color values + unsigned char* colorPtr = colorArray->GetPointer(0); + const int opacity = this->GroupModeEnabled ? 0 : 255; + + this->PrimColors.clear(); + this->PrimColors.reserve(4 * this->CellCellMap->GetSize()); + for (size_t i = 0; i < this->CellCellMap->GetSize(); i++) + { + for (int j = 0; j < 3; j++) + { + this->PrimColors.push_back(colorPtr[this->CellCellMap->GetValue(i) * 3 + j]); + } + this->PrimColors.push_back(opacity); + } +} + +//---------------------------------------------------------------------------- +void vtkCADMapper::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkCADMapper::AddCellIdsToSelectionPrimitives(vtkPolyData* poly, const char* arrayName, + unsigned int processId, unsigned int compositeIndex, vtkIdType selectedId) +{ + this->BuildSelectionCache(arrayName, false, poly); + this->CurrentArrayName = arrayName; + + // If we are selecting an already selected cell, remove it + auto idIterator = this->SelectedIds.find(selectedId); + if (idIterator != this->SelectedIds.end()) + { + if (!this->Selecting) + { + return; + } + for (vtkIdType idx : + this->SelectionCache[std::make_tuple(processId, compositeIndex, selectedId)]) + { + this->ToggleResetColor(idx); + } + this->SelectedIds.erase(idIterator); + return; + } + + if (!this->Selecting) + { + if (this->PreselectedCellId == selectedId) + { + return; + } + this->PreselectedCellId = selectedId; + this->ForceUpdate(); + } + else + { + this->PreselectedCellId = -1; + for (vtkIdType idx : + this->SelectionCache[std::make_tuple(processId, compositeIndex, selectedId)]) + { + this->ToggleSelectColor(idx); + } + this->SelectedIds.emplace(selectedId); + this->ForceUpdate(); + } +} diff --git a/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADMapper.h b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADMapper.h new file mode 100644 index 00000000..598765f3 --- /dev/null +++ b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADMapper.h @@ -0,0 +1,167 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef vtkCADMapper_h +#define vtkCADMapper_h + +#include "CADRepresentationsModule.h" // for export macro + +#include + +#include +#include + +class CADREPRESENTATIONS_EXPORT vtkCADMapper : public vtkOpenGLPolyDataMapper +{ +public: + static vtkCADMapper* New(); + vtkTypeMacro(vtkCADMapper, vtkOpenGLPolyDataMapper); + void PrintSelf(ostream& os, vtkIndent indent) override; + + /** + * Set the opacity value for the given VTK cell. + */ + void SetOpacity(vtkIdType id, unsigned char opacity); + + /** + * Set the reset color value for the given VTK cell. + */ + void ToggleResetColor(vtkIdType id); + + + /** + * Set the select color value for the given VTK cell. + */ + void ToggleSelectColor(vtkIdType id); + + + /** + * Set the preselect color value for the given VTK cell. + */ + void TogglePreselectColor(vtkIdType id); + + /** + * Initialize the map between the VTK cells and OpenGL primitives. + * Initialize also the colors of the primitives using this map + * and the defined colors (Face/Vertex/Edge colors) + */ + void Initialize(); + + /** + * Force BuildCellTextures to execute for the next rendering step. + */ + void ForceUpdate(); + + ///@{ + /** + * Mark the begining and the end of the selection. + */ + void BeginSelect(); + void EndSelect(); + ///@} + + /** + * Create a new selection group, and reset the selection. + */ + void CreateGroup(); + + /** + * If in group mode, set the visibility of the given selection group. + */ + void SetGroupVisibility(int groupIdx, bool visibility); + + /** + * If in group mode, set the opacity of the given selection group. + */ + void SetGroupOpacity(int groupIdx, unsigned char opacity); + + /** + * Enable/disable the Group Mode. In this mode, you visualize + * groups you saved (with the CreateGroup function). Only one + * group can be displayed at a time. + */ + void SetGroupModeEnabled(bool enabled); + + /** + * Reset the current selection. + */ + void ResetSelection(); + +protected: + vtkCADMapper() = default; + ~vtkCADMapper() = default; + + /** + * Called each time a render pass is done. Pushes the primitive colors (PrimColors) + * on the OpenGL side. + */ + void BuildCellTextures( + vtkRenderer* ren, vtkActor* actor, vtkCellArray* prims[4], int representation) override; + +private: + vtkCADMapper(const vtkCADMapper&) = delete; + void operator=(const vtkCADMapper&) = delete; + + /** + * Called during the render pass if the mapper's selection (vtkSelection) changed. + * - Save the preselected id in order to render pre-selection when BuildCellTextures is called + * - If a new selected id is furnished, add it to the SelectedId cache and toggle + * the selection color for the corresponding vtkCell ids using the SelectionCache map. + * + * Selected / preselected ids are values of the data array (arrayName), which allow to + * map geometry elements to their vtkCell counterparts. This mapping is stored in the + * SelectionCache map. + */ + void AddCellIdsToSelectionPrimitives(vtkPolyData* poly, const char* arrayName, + unsigned int processId, unsigned int compositeIndex, vtkIdType selectedId) override; + + /** + * Initialise the primitive colors using color array stored in the input polydata. + * Also initialize the opacity values (depending on current mode). + */ + void InitializePrimColors(); + + // VTK cells to OpenGL primitives map + std::vector> CellToPrimMap; + // Store the currenly selected ids (array values) + std::set SelectedIds; + // Store all the saved selection groups and their respective array name + // (type of cell to select) + std::vector, std::string>> SavedGroups; + // OpenGL primitives color, used in the BuildCellTextures method. + std::vector PrimColors; + // Store the current preselected id (array value) + vtkIdType PreselectedCellId = -1; + bool NeedUpdate = false; + bool Selecting = false; + std::string CurrentArrayName; + bool GroupModeEnabled = false; + + std::vector SavedGroupVisibilities; + std::vector SavedCellOpacities; + + const unsigned char FaceColor[3] = { 255, 255, 255 }; + const unsigned char EdgeColor[3] = { 0, 255, 0 }; + const unsigned char VertexColor[3] = { 255, 128, 0 }; + const unsigned char PreselectionColor[3] = { 0, 0, 255 }; + const unsigned char SelectionColor[3] = { 255, 0, 0 }; + const unsigned char GroupSelectionColor[3] = { 0, 255, 255 }; +}; + +#endif diff --git a/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADRepresentation.cxx b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADRepresentation.cxx new file mode 100644 index 00000000..00bc47a5 --- /dev/null +++ b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADRepresentation.cxx @@ -0,0 +1,283 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "vtkCADMapper.h" +#include "vtkCADRepresentation.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +vtkStandardNewMacro(vtkCADRepresentation); +//---------------------------------------------------------------------------- +vtkCADRepresentation::vtkCADRepresentation() +{ + this->Actor->SetMapper(this->Mapper); + + vtkNew sel; + this->Mapper->SetSelection(sel); + + this->SetArrayIdNames(nullptr, nullptr); +} + +//---------------------------------------------------------------------------- +int vtkCADRepresentation::ProcessViewRequest(vtkInformationRequestKey* request_type, vtkInformation* inInfo, + vtkInformation* outInfo) +{ + if (!this->Superclass::ProcessViewRequest(request_type, inInfo, outInfo)) + { + return 0; + } + + if (request_type == vtkPVView::REQUEST_UPDATE()) + { + vtkPVRenderView::SetPiece(inInfo, this, this->PolyData); + vtkPVRenderView::SetGeometryBounds(inInfo, this, this->PolyData->GetBounds()); + } + else if (request_type == vtkPVView::REQUEST_RENDER()) + { + vtkAlgorithmOutput* producerPort = vtkPVRenderView::GetPieceProducer(inInfo, this); + this->Mapper->SetInputConnection(producerPort); + + if(!this->IsInitialized) + { + this->Mapper->Initialize(); + this->IsInitialized = true; + } + } + + return 1; +} + +//------------------------------------------------------------------------------ +void vtkCADRepresentation::SetVisibility(bool value) +{ + this->Superclass::SetVisibility(value); + this->Actor->SetVisibility(value); +} + +//---------------------------------------------------------------------------- +void vtkCADRepresentation::BeginSelect() +{ + if(this->IsInitialized) + { + this->Mapper->BeginSelect(); + } +} + +//---------------------------------------------------------------------------- +void vtkCADRepresentation::EndSelect() +{ + if(this->IsInitialized) + { + this->Mapper->EndSelect(); + } +} + +//---------------------------------------------------------------------------- +void vtkCADRepresentation::CreateGroup() +{ + if(this->IsInitialized) + { + this->Mapper->CreateGroup(); + } +} + +//---------------------------------------------------------------------------- +void vtkCADRepresentation::SetGroupVisibility(int groupIdx, bool visibility) +{ + if(this->IsInitialized) + { + this->Mapper->SetGroupVisibility(groupIdx, visibility); + } +} + +//---------------------------------------------------------------------------- +void vtkCADRepresentation::SetGroupOpacity(int groupIdx, unsigned char opacity) +{ + if(this->IsInitialized) + { + this->Mapper->SetGroupOpacity(groupIdx, opacity); + } +} + +//---------------------------------------------------------------------------- +void vtkCADRepresentation::SetGroupModeEnabled(bool enabled) +{ + if(this->IsInitialized) + { + this->Mapper->SetGroupModeEnabled(enabled); + } +} + +//---------------------------------------------------------------------------- +void vtkCADRepresentation::Reset() +{ + if(this->IsInitialized) + { + this->Mapper->ResetSelection(); + } +} + +//------------------------------------------------------------------------------ +int vtkCADRepresentation::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + + // Saying INPUT_IS_OPTIONAL() is essential, since representations don't have + // any inputs on client-side (in client-server, client-render-server mode) and + // render-server-side (in client-render-server mode). + info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1); + + return 1; +} + +//------------------------------------------------------------------------------ +int vtkCADRepresentation::RequestData( + vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector) +{ + if (inputVector[0]->GetNumberOfInformationObjects() == 1) + { + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkPolyData* polyData = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + this->PolyData->ShallowCopy(polyData); + } + else + { + this->PolyData->Initialize(); + } + + return this->Superclass::RequestData(request, inputVector, outputVector); +} + +//------------------------------------------------------------------------------ +bool vtkCADRepresentation::AddToView(vtkView* view) +{ + vtkPVRenderView* rview = vtkPVRenderView::SafeDownCast(view); + if (rview) + { + rview->GetRenderer()->AddActor(this->Actor); + + // Indicate that this is prop that we are rendering when hardware selection + // is enabled. + rview->RegisterPropForHardwareSelection(this, this->Actor); + return this->Superclass::AddToView(view); + } + return false; +} + +//------------------------------------------------------------------------------ +bool vtkCADRepresentation::RemoveFromView(vtkView* view) +{ + vtkPVRenderView* rview = vtkPVRenderView::SafeDownCast(view); + if (rview) + { + rview->GetRenderer()->RemoveActor(this->Actor); + rview->UnRegisterPropForHardwareSelection(this, this->Actor); + return this->Superclass::RemoveFromView(view); + } + return false; +} + +//---------------------------------------------------------------------------- +void vtkCADRepresentation::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +void vtkCADRepresentation::SetSelectionConnection(vtkAlgorithmOutput* input) +{ + // Copied from vtkCompositeRepresentation + if (!input) + { + return; + } + + vtkMultiProcessController* controller = vtkMultiProcessController::GetGlobalController(); + int numPiece = controller->GetNumberOfProcesses(); + int piece = controller->GetLocalProcessId(); + input->GetProducer()->UpdatePiece(piece, numPiece, 0); + + vtkSmartPointer sel; + int actualNbPieces = numPiece; + + vtkSMSession* session = + vtkSMSession::SafeDownCast(vtkProcessModule::GetProcessModule()->GetSession()); + if (session) + { + actualNbPieces = session->GetNumberOfProcesses(vtkPVSession::DATA_SERVER); + } + + // in order to handle the case where we are connected to a parallel server using + // local rendering, we have to compare the number of processes here + if (numPiece < actualNbPieces && piece == 0) + { + vtkSelection* localSel = + vtkSelection::SafeDownCast(input->GetProducer()->GetOutputDataObject(0)); + sel = vtkSmartPointer::New(); + sel->ShallowCopy(localSel); + + for (int i = 1; i < actualNbPieces; i++) + { + input->GetProducer()->UpdatePiece(i, actualNbPieces, 0); + localSel = vtkSelection::SafeDownCast(input->GetProducer()->GetOutputDataObject(0)); + if (localSel->GetNumberOfNodes() > 1) + { + vtkWarningMacro("Only the first node of a selection will be considered."); + } + vtkSelectionNode* node = localSel->GetNode(0); + node->GetProperties()->Set(vtkSelectionNode::PROCESS_ID(), i); + sel->AddNode(localSel->GetNode(0)); + } + } + else + { + sel = vtkSelection::SafeDownCast(input->GetProducer()->GetOutputDataObject(0)); + if (sel->GetNumberOfNodes() > 1) + { + vtkWarningMacro("Only the first node of a selection will be considered."); + } + sel->GetNode(0)->GetProperties()->Set(vtkSelectionNode::PROCESS_ID(), piece); + } + + this->Mapper->GetSelection()->ShallowCopy(sel); +} + +//---------------------------------------------------------------------------- +void vtkCADRepresentation::SetArrayIdNames(const char* pointArray, const char* cellArray) +{ + vtkCADMapper* mapper = vtkCADMapper::SafeDownCast(this->Mapper); + mapper->SetPointIdArrayName(pointArray ? pointArray : "vtkOriginalPointIds"); + mapper->SetCellIdArrayName(cellArray ? cellArray : "vtkOriginalCellIds"); +} diff --git a/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADRepresentation.h b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADRepresentation.h new file mode 100644 index 00000000..59e74d3f --- /dev/null +++ b/src/Plugins/CADRepresentation/cadRepresentations/CADRepresentations/vtkCADRepresentation.h @@ -0,0 +1,122 @@ +// Copyright (C) 2023 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef vtkCADRepresentation_h +#define vtkCADRepresentation_h + +#include "CADRepresentationsModule.h" // for export macro + +#include + +#include +#include +#include +#include + +class vtkActor; +class vtkCADMapper; + +enum SelectionType : unsigned char +{ + GeometrySolids = 0, + GeometryVertices, + GeometryEdges, + GeometryFaces, + SelectionTypeCount +}; +class CADREPRESENTATIONS_EXPORT vtkCADRepresentation + : public vtkPVDataRepresentation +{ +public: + static vtkCADRepresentation* New(); + vtkTypeMacro(vtkCADRepresentation, vtkPVDataRepresentation); + void PrintSelf(ostream& os, vtkIndent indent) override; + + int ProcessViewRequest(vtkInformationRequestKey* request_type, vtkInformation* inInfo, + vtkInformation* outInfo) override; + + /** + * Set the pre-configured selection source for making the selection. + * The vtkSelection is obtained internally and forwarded to the mapper + */ + void SetSelectionConnection(vtkAlgorithmOutput* input); + + /** + * Set the visibility of the rendered actor. + */ + void SetVisibility(bool val) override; + + void Reset(); + void BeginSelect(); + void EndSelect(); + + /** + * Create a new selection group, and reset the selection. + * Forwarded to the mapper. + */ + void CreateGroup(); + + /** + * If in group mode, set the visibility of the given selection group. + * Forwarded to the mapper. + */ + void SetGroupVisibility(int groupIdx, bool visibility); + + /** + * If in group mode, set the opacity of the given selection group. + * Forwarded to the mapper. + */ + void SetGroupOpacity(int groupIdx, unsigned char opacity); + + /** + * Enable/disable the Group Mode. In this mode, you visualize + * groups you saved (with the CreateGroup function). Only one + * group can be displayed at a time. + * Forwarded to the mapper. + */ + void SetGroupModeEnabled(bool enabled); + + /** + * Add a shape to the list of selected shapes that will + * be modified by setOpacity / toggleColor functions + * (for debugging purposes). + */ + void AddShape(vtkIdType groupId, vtkIdType cellId); + + void SetArrayIdNames(const char* pointArray, const char* cellArray) override; +protected: + vtkCADRepresentation(); + ~vtkCADRepresentation() = default; + + int FillInputPortInformation(int port, vtkInformation* info) override; + int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override; + bool AddToView(vtkView* view) override; + bool RemoveFromView(vtkView* view) override; + + bool IsInitialized = false; + vtkNew Actor; + vtkNew Mapper; + vtkNew PolyData; + +private: + vtkCADRepresentation(const vtkCADRepresentation&) = delete; + void operator=(const vtkCADRepresentation&) = delete; +}; + +#endif // vtkCADRepresentation_h diff --git a/src/Plugins/CADRepresentation/cadRepresentations/CMakeLists.txt b/src/Plugins/CADRepresentation/cadRepresentations/CMakeLists.txt new file mode 100644 index 00000000..c946dca3 --- /dev/null +++ b/src/Plugins/CADRepresentation/cadRepresentations/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (C) 2023 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +paraview_add_plugin(CADRepresentation + VERSION "1.0" + MODULES CADRepresentations + MODULE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/CADRepresentations/vtk.module" + XML_DOCUMENTATION OFF) diff --git a/src/Plugins/CADRepresentation/cadRepresentations/paraview.plugin b/src/Plugins/CADRepresentation/cadRepresentations/paraview.plugin new file mode 100644 index 00000000..239ebf13 --- /dev/null +++ b/src/Plugins/CADRepresentation/cadRepresentations/paraview.plugin @@ -0,0 +1,9 @@ +NAME + CADRepresentation +DESCRIPTION + CADViewer plugin providing representations. +REQUIRES_MODULES + ParaView::RemotingViews + VTK::CommonCore + VTK::CommonDataModel + VTK::RenderingOpenGL2 diff --git a/src/Plugins/CMakeLists.txt b/src/Plugins/CMakeLists.txt index efe831b2..e77fb91d 100644 --- a/src/Plugins/CMakeLists.txt +++ b/src/Plugins/CMakeLists.txt @@ -33,6 +33,7 @@ SET(_subdirs GaussToCell VoroGauss BivariateRepresentations + CADRepresentation ) IF(NOT SALOME_LIGHT_ONLY)