From e2fcf45e5c5da6c988ecf4dd801700120da0490a Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 17 Nov 2025 11:31:22 +0100 Subject: [PATCH 01/26] [Visual] Introction of VisualMesh --- Sofa/Component/Visual/CMakeLists.txt | 2 + .../src/sofa/component/visual/VisualMesh.cpp | 143 ++++++++++++++++++ .../src/sofa/component/visual/VisualMesh.h | 58 +++++++ .../Visual/src/sofa/component/visual/init.cpp | 2 + examples/Component/Visual/VisualMesh.scn | 25 +++ 5 files changed, 230 insertions(+) create mode 100644 Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp create mode 100644 Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h create mode 100644 examples/Component/Visual/VisualMesh.scn diff --git a/Sofa/Component/Visual/CMakeLists.txt b/Sofa/Component/Visual/CMakeLists.txt index a3f9e277011..e81df5befdd 100644 --- a/Sofa/Component/Visual/CMakeLists.txt +++ b/Sofa/Component/Visual/CMakeLists.txt @@ -17,6 +17,7 @@ set(HEADER_FILES ${SOFACOMPONENTVISUAL_SOURCE_DIR}/Visual3DText.h ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualBoundingBox.h ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualGrid.h + ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualMesh.h ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualModelImpl.h ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualPointCloud.h ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualPointCloud.inl @@ -38,6 +39,7 @@ set(SOURCE_FILES ${SOFACOMPONENTVISUAL_SOURCE_DIR}/Visual3DText.cpp ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualBoundingBox.cpp ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualGrid.cpp + ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualMesh.cpp ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualModelImpl.cpp ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualPointCloud.cpp ${SOFACOMPONENTVISUAL_SOURCE_DIR}/VisualStyle.cpp diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp new file mode 100644 index 00000000000..5e1748356a0 --- /dev/null +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp @@ -0,0 +1,143 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2006 INRIA, USTL, UJF, CNRS, MGH * +* * +* This program 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 program 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 program. If not, see . * +******************************************************************************* +* Authors: The SOFA Team and external contributors (see Authors.txt) * +* * +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#include +#include +#include + +namespace sofa::component::visual +{ + +void registerVisualMesh(sofa::core::ObjectFactory* factory) +{ + factory->registerObjects(core::ObjectRegistrationData("Render a mesh") + .add() + ); +} + +VisualMesh::VisualMesh() + : d_position(initData(&d_position, "position", "The position of the vertices of mesh")) + , d_elementSpace(initData(&d_elementSpace, 0.333_sreal, "elementSpace", + "The space between element (scalar between 0 and 1)")) + , l_topology(initLink("topology", "Link to a topology containing elements")) +{} + +void VisualMesh::init() +{ + VisualModel::init(); + + if (!this->isComponentStateInvalid()) + { + this->validateTopology(); + } + + if (!this->isComponentStateInvalid()) + { + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Valid); + } +} + + +void VisualMesh::drawTetrahedra(helper::visual::DrawTool* drawTool) +{ + if (!l_topology) + return; + + const auto& elements = l_topology->getTetrahedra(); + const auto& facets = l_topology->getTriangles(); + + static constexpr std::size_t NumberTrianglesInTetrahedron = 4; + static constexpr std::size_t NumberVerticesInTriangle = 3; + m_renderedPoints.resize(elements.size() * NumberTrianglesInTetrahedron * NumberVerticesInTriangle); + m_renderedColors.resize(elements.size() * NumberTrianglesInTetrahedron * NumberVerticesInTriangle); + + const auto elementSpace = d_elementSpace.getValue(); + const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); + + auto pointsIt = m_renderedPoints.begin(); + auto colorIt = m_renderedColors.begin(); + + for (sofa::Size i = 0; i < elements.size(); ++i) + { + const auto& element = elements[i]; + const auto& facetsInElement = l_topology->getTrianglesInTetrahedron(i); + assert(facetsInElement.size() == NumberTrianglesInTetrahedron); + + sofa::type::Vec3 center{}; + for (sofa::Size vId = 0; vId < sofa::geometry::Tetrahedron::NumberOfNodes; ++vId) + { + center += positionAccessor[element[vId]]; + } + center /= sofa::geometry::Tetrahedron::NumberOfNodes; + + static constexpr std::array colors{ + sofa::type::RGBAColor::blue(), + sofa::type::RGBAColor::black(), + sofa::type::RGBAColor(0.0f, 0.5f, 1.0f, 1.0f), + sofa::type::RGBAColor::cyan(), + }; + + std::size_t j{}; + for (const auto& facetId : facetsInElement) + { + const auto& facet = facets[facetId]; + for (const auto vId : facet) + { + *pointsIt++ = (positionAccessor[vId] - center) * (1._sreal - elementSpace) + center; + *colorIt++ = colors[j]; + } + ++j; + } + } + drawTool->drawTriangles(m_renderedPoints, m_renderedColors); +} + +void VisualMesh::doDrawVisual(const core::visual::VisualParams* vparams) +{ + auto* drawTool = vparams->drawTool(); + + vparams->drawTool()->disableLighting(); + + drawTetrahedra(drawTool); +} + +void VisualMesh::validateTopology() +{ + if (l_topology.empty()) + { + msg_info() << "Link to Topology container should be set to ensure right behavior. First " + "Topology found in current context will be used."; + l_topology.set(this->getContext()->getMeshTopologyLink()); + } + + if (l_topology == nullptr) + { + msg_error() << "No topology component found at path: " << this->l_topology.getLinkedPath() + << ", nor in current context: " << this->getContext()->name + << ". Object must have a BaseMeshTopology. " + << "The list of available BaseMeshTopology components is: " + << sofa::core::ObjectFactory::getInstance() + ->listClassesDerivedFrom(); + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + } +} + +} // namespace sofa::component::visual diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h new file mode 100644 index 00000000000..d46c0c22daf --- /dev/null +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h @@ -0,0 +1,58 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2006 INRIA, USTL, UJF, CNRS, MGH * +* * +* This program 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 program 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 program. If not, see . * +******************************************************************************* +* Authors: The SOFA Team and external contributors (see Authors.txt) * +* * +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#pragma once +#include +#include +#include + +namespace sofa::component::visual +{ + +class VisualMesh : public core::visual::VisualModel +{ +public: + SOFA_CLASS(VisualMesh, core::visual::VisualModel); + + Data> d_position; + Data d_elementSpace; + + /// The topology will give access to the elements + sofa::SingleLink l_topology; + + + void init() override; + +protected: + + VisualMesh(); + + void drawTetrahedra(helper::visual::DrawTool* drawTool); + void doDrawVisual(const core::visual::VisualParams* vparams) override; + + void validateTopology(); + + sofa::type::vector< sofa::type::Vec3 > m_renderedPoints; + sofa::type::vector< sofa::type::RGBAColor > m_renderedColors; +}; + +} diff --git a/Sofa/Component/Visual/src/sofa/component/visual/init.cpp b/Sofa/Component/Visual/src/sofa/component/visual/init.cpp index 27ee33e1bb0..5d5258908f7 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/init.cpp +++ b/Sofa/Component/Visual/src/sofa/component/visual/init.cpp @@ -40,6 +40,7 @@ extern void registerVisualPointCloud(sofa::core::ObjectFactory* factory); extern void registerVisualStyle(sofa::core::ObjectFactory* factory); extern void registerVisualTransform(sofa::core::ObjectFactory* factory); extern void registerVisualVectorField(sofa::core::ObjectFactory* factory); +extern void registerVisualMesh(sofa::core::ObjectFactory* factory); extern "C" { SOFA_EXPORT_DYNAMIC_LIBRARY void initExternalModule(); @@ -79,6 +80,7 @@ void registerObjects(sofa::core::ObjectFactory* factory) registerVisualStyle(factory); registerVisualTransform(factory); registerVisualVectorField(factory); + registerVisualMesh(factory); } void init() diff --git a/examples/Component/Visual/VisualMesh.scn b/examples/Component/Visual/VisualMesh.scn new file mode 100644 index 00000000000..1a4ffb6271c --- /dev/null +++ b/examples/Component/Visual/VisualMesh.scn @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + From fcd91a98643fd00cc0b5f06785d3108eb5df8c73 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 17 Nov 2025 11:43:09 +0100 Subject: [PATCH 02/26] draw hexahedra --- .../src/sofa/component/visual/VisualMesh.cpp | 58 ++++++++++++++++++- .../src/sofa/component/visual/VisualMesh.h | 1 + examples/Component/Visual/VisualMesh.scn | 21 ++++++- 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp index 5e1748356a0..ab4eeafa025 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp @@ -55,7 +55,6 @@ void VisualMesh::init() } } - void VisualMesh::drawTetrahedra(helper::visual::DrawTool* drawTool) { if (!l_topology) @@ -110,6 +109,62 @@ void VisualMesh::drawTetrahedra(helper::visual::DrawTool* drawTool) drawTool->drawTriangles(m_renderedPoints, m_renderedColors); } +void VisualMesh::drawHexahedra(helper::visual::DrawTool* drawTool) +{ + if (!l_topology) + return; + + const auto& elements = l_topology->getHexahedra(); + const auto& facets = l_topology->getQuads(); + + static constexpr std::size_t NumberQuadsInHexahedron = 6; + static constexpr std::size_t NumberVerticesInQuad = 4; + m_renderedPoints.resize(elements.size() * NumberQuadsInHexahedron * NumberVerticesInQuad); + m_renderedColors.resize(elements.size() * NumberQuadsInHexahedron * NumberVerticesInQuad); + + const auto elementSpace = d_elementSpace.getValue(); + const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); + + auto pointsIt = m_renderedPoints.begin(); + auto colorIt = m_renderedColors.begin(); + + for (sofa::Size i = 0; i < elements.size(); ++i) + { + const auto& element = elements[i]; + const auto& facetsInElement = l_topology->getQuadsInHexahedron(i); + assert(facetsInElement.size() == NumberQuadsInHexahedron); + + sofa::type::Vec3 center{}; + for (sofa::Size vId = 0; vId < sofa::geometry::Hexahedron::NumberOfNodes; ++vId) + { + center += positionAccessor[element[vId]]; + } + center /= sofa::geometry::Hexahedron::NumberOfNodes; + + static constexpr std::array colors { + sofa::type::RGBAColor(0.7f,0.7f,0.1f,1.f), + sofa::type::RGBAColor(0.7f,0.0f,0.0f,1.f), + sofa::type::RGBAColor(0.0f,0.7f,0.0f,1.f), + sofa::type::RGBAColor(0.0f,0.0f,0.7f,1.f), + sofa::type::RGBAColor(0.1f,0.7f,0.7f,1.f), + sofa::type::RGBAColor(0.7f,0.1f,0.7f,1.f) + }; + + std::size_t j{}; + for (const auto& facetId : facetsInElement) + { + const auto& facet = facets[facetId]; + for (const auto vId : facet) + { + *pointsIt++ = (positionAccessor[vId] - center) * (1._sreal - elementSpace) + center; + *colorIt++ = colors[j]; + } + ++j; + } + } + drawTool->drawQuads(m_renderedPoints, m_renderedColors); +} + void VisualMesh::doDrawVisual(const core::visual::VisualParams* vparams) { auto* drawTool = vparams->drawTool(); @@ -117,6 +172,7 @@ void VisualMesh::doDrawVisual(const core::visual::VisualParams* vparams) vparams->drawTool()->disableLighting(); drawTetrahedra(drawTool); + drawHexahedra(drawTool); } void VisualMesh::validateTopology() diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h index d46c0c22daf..7c8f58b874f 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h @@ -47,6 +47,7 @@ class VisualMesh : public core::visual::VisualModel VisualMesh(); void drawTetrahedra(helper::visual::DrawTool* drawTool); + void drawHexahedra(helper::visual::DrawTool* drawTool); void doDrawVisual(const core::visual::VisualParams* vparams) override; void validateTopology(); diff --git a/examples/Component/Visual/VisualMesh.scn b/examples/Component/Visual/VisualMesh.scn index 1a4ffb6271c..79eedac006d 100644 --- a/examples/Component/Visual/VisualMesh.scn +++ b/examples/Component/Visual/VisualMesh.scn @@ -1,7 +1,7 @@ - + @@ -14,12 +14,27 @@ - + + + + + + + + + + + + + + + + + From e8f79464d4c2293bde8da8d8abf0ac4951d5cc93 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 17 Nov 2025 11:50:22 +0100 Subject: [PATCH 03/26] factorize element center --- .../src/sofa/component/visual/VisualMesh.cpp | 14 ++------------ .../Visual/src/sofa/component/visual/VisualMesh.h | 12 ++++++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp index ab4eeafa025..127f1d85bc2 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp @@ -80,12 +80,7 @@ void VisualMesh::drawTetrahedra(helper::visual::DrawTool* drawTool) const auto& facetsInElement = l_topology->getTrianglesInTetrahedron(i); assert(facetsInElement.size() == NumberTrianglesInTetrahedron); - sofa::type::Vec3 center{}; - for (sofa::Size vId = 0; vId < sofa::geometry::Tetrahedron::NumberOfNodes; ++vId) - { - center += positionAccessor[element[vId]]; - } - center /= sofa::geometry::Tetrahedron::NumberOfNodes; + const sofa::type::Vec3 center = elementCenter(positionAccessor.ref(), element); static constexpr std::array colors{ sofa::type::RGBAColor::blue(), @@ -134,12 +129,7 @@ void VisualMesh::drawHexahedra(helper::visual::DrawTool* drawTool) const auto& facetsInElement = l_topology->getQuadsInHexahedron(i); assert(facetsInElement.size() == NumberQuadsInHexahedron); - sofa::type::Vec3 center{}; - for (sofa::Size vId = 0; vId < sofa::geometry::Hexahedron::NumberOfNodes; ++vId) - { - center += positionAccessor[element[vId]]; - } - center /= sofa::geometry::Hexahedron::NumberOfNodes; + const sofa::type::Vec3 center = elementCenter(positionAccessor.ref(), element); static constexpr std::array colors { sofa::type::RGBAColor(0.7f,0.7f,0.1f,1.f), diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h index 7c8f58b874f..95e65a5b6fc 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h @@ -54,6 +54,18 @@ class VisualMesh : public core::visual::VisualModel sofa::type::vector< sofa::type::Vec3 > m_renderedPoints; sofa::type::vector< sofa::type::RGBAColor > m_renderedColors; + + template + sofa::type::Vec3 elementCenter(const type::vector& position, const ElementType& element) + { + sofa::type::Vec3 center{}; + for (sofa::Size vId = 0; vId < element.size(); ++vId) + { + center += position[element[vId]]; + } + center /= element.size(); + return center; + } }; } From b4e6fedc298e57d7fbcd9cd64960c159e52b45e4 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 17 Nov 2025 11:59:23 +0100 Subject: [PATCH 04/26] factorize definition of points and colors --- .../src/sofa/component/visual/VisualMesh.cpp | 24 ++---------------- .../src/sofa/component/visual/VisualMesh.h | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp index 127f1d85bc2..daa11faf0fc 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp @@ -89,17 +89,7 @@ void VisualMesh::drawTetrahedra(helper::visual::DrawTool* drawTool) sofa::type::RGBAColor::cyan(), }; - std::size_t j{}; - for (const auto& facetId : facetsInElement) - { - const auto& facet = facets[facetId]; - for (const auto vId : facet) - { - *pointsIt++ = (positionAccessor[vId] - center) * (1._sreal - elementSpace) + center; - *colorIt++ = colors[j]; - } - ++j; - } + setPointsAndColors(facetsInElement, facets, positionAccessor.ref(), center, elementSpace, pointsIt, colorIt, colors); } drawTool->drawTriangles(m_renderedPoints, m_renderedColors); } @@ -140,17 +130,7 @@ void VisualMesh::drawHexahedra(helper::visual::DrawTool* drawTool) sofa::type::RGBAColor(0.7f,0.1f,0.7f,1.f) }; - std::size_t j{}; - for (const auto& facetId : facetsInElement) - { - const auto& facet = facets[facetId]; - for (const auto vId : facet) - { - *pointsIt++ = (positionAccessor[vId] - center) * (1._sreal - elementSpace) + center; - *colorIt++ = colors[j]; - } - ++j; - } + setPointsAndColors(facetsInElement, facets, positionAccessor.ref(), center, elementSpace, pointsIt, colorIt, colors); } drawTool->drawQuads(m_renderedPoints, m_renderedColors); } diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h index 95e65a5b6fc..035d40f16ac 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h @@ -66,6 +66,31 @@ class VisualMesh : public core::visual::VisualModel center /= element.size(); return center; } + + template + void setPointsAndColors( + const sofa::type::fixed_array facetsInElement, + const sofa::type::vector& facets, + const type::vector& position, + const type::Vec3& elementCenter, + SReal elementSpace, + sofa::type::vector< sofa::type::Vec3 >::iterator& pointsIt, + sofa::type::vector< sofa::type::RGBAColor >::iterator& colorIt, + const std::array& colors + ) + { + std::size_t j{}; + for (const auto& facetId : facetsInElement) + { + const auto& facet = facets[facetId]; + for (const auto vId : facet) + { + *pointsIt++ = (position[vId] - elementCenter) * (1._sreal - elementSpace) + elementCenter; + *colorIt++ = colors[j]; + } + ++j; + } + } }; } From f547805ee05a83b58a9ca08468f1dd8229474914 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 17 Nov 2025 12:20:05 +0100 Subject: [PATCH 05/26] draw triangles --- .../src/sofa/component/visual/VisualMesh.cpp | 48 ++++++++++++++++++- .../src/sofa/component/visual/VisualMesh.h | 3 +- examples/Component/Visual/VisualMesh.scn | 16 ++++++- 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp index daa11faf0fc..dd958f2a5af 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp @@ -35,10 +35,12 @@ void registerVisualMesh(sofa::core::ObjectFactory* factory) VisualMesh::VisualMesh() : d_position(initData(&d_position, "position", "The position of the vertices of mesh")) - , d_elementSpace(initData(&d_elementSpace, 0.333_sreal, "elementSpace", + , d_elementSpace(initData(&d_elementSpace, 0.15_sreal, "elementSpace", "The space between element (scalar between 0 and 1)")) , l_topology(initLink("topology", "Link to a topology containing elements")) -{} +{ +} + void VisualMesh::init() { @@ -55,6 +57,41 @@ void VisualMesh::init() } } +void VisualMesh::drawTriangles(helper::visual::DrawTool* drawTool) +{ + if (!l_topology) + return; + + const auto& elements = l_topology->getTriangles(); + + static constexpr std::size_t NumberVerticesInTriangle = 3; + m_renderedPoints.resize(elements.size() * NumberVerticesInTriangle); + m_renderedColors.resize(elements.size() * NumberVerticesInTriangle); + + const auto elementSpace = d_elementSpace.getValue(); + const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); + + auto pointsIt = m_renderedPoints.begin(); + auto colorIt = m_renderedColors.begin(); + + for (sofa::Size i = 0; i < elements.size(); ++i) + { + const auto& element = elements[i]; + + const sofa::type::Vec3 center = elementCenter(positionAccessor.ref(), element); + + static constexpr std::array colors{ + sofa::type::RGBAColor::green(), + sofa::type::RGBAColor(0, 0.5, 0.5, 1), + sofa::type::RGBAColor::blue(), + }; + + std::array facetsInElement{i}; + setPointsAndColors(facetsInElement, elements, positionAccessor.ref(), center, elementSpace, pointsIt, colorIt, {colors[i%NumberVerticesInTriangle]}); + } + drawTool->drawTriangles(m_renderedPoints, m_renderedColors); +} + void VisualMesh::drawTetrahedra(helper::visual::DrawTool* drawTool) { if (!l_topology) @@ -141,6 +178,13 @@ void VisualMesh::doDrawVisual(const core::visual::VisualParams* vparams) vparams->drawTool()->disableLighting(); + const auto hasTetra = l_topology && !l_topology->getTetrahedra().empty(); + const auto hasHexa = l_topology && !l_topology->getHexahedra().empty(); + + if (!hasTetra && !hasHexa) + { + drawTriangles(drawTool); + } drawTetrahedra(drawTool); drawHexahedra(drawTool); } diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h index 035d40f16ac..d1dd02c71cc 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h @@ -46,6 +46,7 @@ class VisualMesh : public core::visual::VisualModel VisualMesh(); + void drawTriangles(helper::visual::DrawTool* drawTool); void drawTetrahedra(helper::visual::DrawTool* drawTool); void drawHexahedra(helper::visual::DrawTool* drawTool); void doDrawVisual(const core::visual::VisualParams* vparams) override; @@ -69,7 +70,7 @@ class VisualMesh : public core::visual::VisualModel template void setPointsAndColors( - const sofa::type::fixed_array facetsInElement, + const std::array facetsInElement, const sofa::type::vector& facets, const type::vector& position, const type::Vec3& elementCenter, diff --git a/examples/Component/Visual/VisualMesh.scn b/examples/Component/Visual/VisualMesh.scn index 79eedac006d..bb08e1792b1 100644 --- a/examples/Component/Visual/VisualMesh.scn +++ b/examples/Component/Visual/VisualMesh.scn @@ -26,8 +26,8 @@ - - + + @@ -37,4 +37,16 @@ + + + + + + + + + + + + From 57ddb3545b0b083dd576329df15811dc940074ef Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 20 Nov 2025 15:15:19 +0100 Subject: [PATCH 06/26] modify color vector only if elements vector change --- .../src/sofa/component/visual/VisualMesh.cpp | 81 +++++++++++++------ .../src/sofa/component/visual/VisualMesh.h | 9 +-- .../Type/src/sofa/type/RGBAColor.cpp | 3 +- Sofa/framework/Type/src/sofa/type/RGBAColor.h | 4 +- 4 files changed, 62 insertions(+), 35 deletions(-) diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp index dd958f2a5af..172e75fde15 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp @@ -64,15 +64,12 @@ void VisualMesh::drawTriangles(helper::visual::DrawTool* drawTool) const auto& elements = l_topology->getTriangles(); - static constexpr std::size_t NumberVerticesInTriangle = 3; - m_renderedPoints.resize(elements.size() * NumberVerticesInTriangle); - m_renderedColors.resize(elements.size() * NumberVerticesInTriangle); + m_renderedPoints.resize(elements.size() * sofa::geometry::Triangle::NumberOfNodes); const auto elementSpace = d_elementSpace.getValue(); const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); auto pointsIt = m_renderedPoints.begin(); - auto colorIt = m_renderedColors.begin(); for (sofa::Size i = 0; i < elements.size(); ++i) { @@ -80,18 +77,46 @@ void VisualMesh::drawTriangles(helper::visual::DrawTool* drawTool) const sofa::type::Vec3 center = elementCenter(positionAccessor.ref(), element); + std::array facetsInElement{i}; + setPoints(facetsInElement, elements, positionAccessor.ref(), center, elementSpace, pointsIt); + } + + while (m_renderedColors.size() < elements.size() * sofa::geometry::Triangle::NumberOfNodes) + { static constexpr std::array colors{ - sofa::type::RGBAColor::green(), - sofa::type::RGBAColor(0, 0.5, 0.5, 1), - sofa::type::RGBAColor::blue(), + type::makeHomogeneousArray( sofa::type::RGBAColor::green()), + type::makeHomogeneousArray(sofa::type::RGBAColor::teal()), + type::makeHomogeneousArray(sofa::type::RGBAColor::blue()), }; - std::array facetsInElement{i}; - setPointsAndColors(facetsInElement, elements, positionAccessor.ref(), center, elementSpace, pointsIt, colorIt, {colors[i%NumberVerticesInTriangle]}); + const auto elementId = m_renderedColors.size() / sofa::geometry::Triangle::NumberOfNodes; + const auto triangleColor = colors[elementId % colors.size()]; + + m_renderedColors.insert(m_renderedColors.end(), triangleColor.begin(), triangleColor.end()); } + drawTool->drawTriangles(m_renderedPoints, m_renderedColors); } +namespace +{ +template +std::array +constexpr generateElementColors(const std::array& facetColors) +{ + std::array verticeColors; + auto verticeColorsIt = verticeColors.begin(); + for (const auto& c : facetColors) + { + for (std::size_t i = 0; i < NumberVerticesInFacet; ++i) + { + *verticeColorsIt++ = c; + } + } + return verticeColors; +} +} + void VisualMesh::drawTetrahedra(helper::visual::DrawTool* drawTool) { if (!l_topology) @@ -101,15 +126,12 @@ void VisualMesh::drawTetrahedra(helper::visual::DrawTool* drawTool) const auto& facets = l_topology->getTriangles(); static constexpr std::size_t NumberTrianglesInTetrahedron = 4; - static constexpr std::size_t NumberVerticesInTriangle = 3; - m_renderedPoints.resize(elements.size() * NumberTrianglesInTetrahedron * NumberVerticesInTriangle); - m_renderedColors.resize(elements.size() * NumberTrianglesInTetrahedron * NumberVerticesInTriangle); + m_renderedPoints.resize(elements.size() * NumberTrianglesInTetrahedron * sofa::geometry::Triangle::NumberOfNodes); const auto elementSpace = d_elementSpace.getValue(); const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); auto pointsIt = m_renderedPoints.begin(); - auto colorIt = m_renderedColors.begin(); for (sofa::Size i = 0; i < elements.size(); ++i) { @@ -119,15 +141,20 @@ void VisualMesh::drawTetrahedra(helper::visual::DrawTool* drawTool) const sofa::type::Vec3 center = elementCenter(positionAccessor.ref(), element); - static constexpr std::array colors{ + setPoints(facetsInElement, facets, positionAccessor.ref(), center, elementSpace, pointsIt); + } + + while (m_renderedColors.size() < elements.size() * NumberTrianglesInTetrahedron * sofa::geometry::Triangle::NumberOfNodes) + { + static constexpr std::array colors = generateElementColors({ sofa::type::RGBAColor::blue(), sofa::type::RGBAColor::black(), - sofa::type::RGBAColor(0.0f, 0.5f, 1.0f, 1.0f), - sofa::type::RGBAColor::cyan(), - }; + sofa::type::RGBAColor::azure(), + sofa::type::RGBAColor::cyan()}); - setPointsAndColors(facetsInElement, facets, positionAccessor.ref(), center, elementSpace, pointsIt, colorIt, colors); + m_renderedColors.insert(m_renderedColors.end(), colors.begin(), colors.end()); } + drawTool->drawTriangles(m_renderedPoints, m_renderedColors); } @@ -140,15 +167,12 @@ void VisualMesh::drawHexahedra(helper::visual::DrawTool* drawTool) const auto& facets = l_topology->getQuads(); static constexpr std::size_t NumberQuadsInHexahedron = 6; - static constexpr std::size_t NumberVerticesInQuad = 4; - m_renderedPoints.resize(elements.size() * NumberQuadsInHexahedron * NumberVerticesInQuad); - m_renderedColors.resize(elements.size() * NumberQuadsInHexahedron * NumberVerticesInQuad); + m_renderedPoints.resize(elements.size() * NumberQuadsInHexahedron * sofa::geometry::Quad::NumberOfNodes); const auto elementSpace = d_elementSpace.getValue(); const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); auto pointsIt = m_renderedPoints.begin(); - auto colorIt = m_renderedColors.begin(); for (sofa::Size i = 0; i < elements.size(); ++i) { @@ -158,17 +182,22 @@ void VisualMesh::drawHexahedra(helper::visual::DrawTool* drawTool) const sofa::type::Vec3 center = elementCenter(positionAccessor.ref(), element); - static constexpr std::array colors { + setPoints(facetsInElement, facets, positionAccessor.ref(), center, elementSpace, pointsIt); + } + + while (m_renderedColors.size() < elements.size() * NumberQuadsInHexahedron * sofa::geometry::Quad::NumberOfNodes) + { + static constexpr std::array colors = generateElementColors({ sofa::type::RGBAColor(0.7f,0.7f,0.1f,1.f), sofa::type::RGBAColor(0.7f,0.0f,0.0f,1.f), sofa::type::RGBAColor(0.0f,0.7f,0.0f,1.f), sofa::type::RGBAColor(0.0f,0.0f,0.7f,1.f), sofa::type::RGBAColor(0.1f,0.7f,0.7f,1.f), - sofa::type::RGBAColor(0.7f,0.1f,0.7f,1.f) - }; + sofa::type::RGBAColor(0.7f,0.1f,0.7f,1.f)}); - setPointsAndColors(facetsInElement, facets, positionAccessor.ref(), center, elementSpace, pointsIt, colorIt, colors); + m_renderedColors.insert(m_renderedColors.end(), colors.begin(), colors.end()); } + drawTool->drawQuads(m_renderedPoints, m_renderedColors); } diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h index d1dd02c71cc..c73e380bc85 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h @@ -69,27 +69,22 @@ class VisualMesh : public core::visual::VisualModel } template - void setPointsAndColors( + void setPoints( const std::array facetsInElement, const sofa::type::vector& facets, const type::vector& position, const type::Vec3& elementCenter, SReal elementSpace, - sofa::type::vector< sofa::type::Vec3 >::iterator& pointsIt, - sofa::type::vector< sofa::type::RGBAColor >::iterator& colorIt, - const std::array& colors + sofa::type::vector< sofa::type::Vec3 >::iterator& pointsIt ) { - std::size_t j{}; for (const auto& facetId : facetsInElement) { const auto& facet = facets[facetId]; for (const auto vId : facet) { *pointsIt++ = (position[vId] - elementCenter) * (1._sreal - elementSpace) + elementCenter; - *colorIt++ = colors[j]; } - ++j; } } }; diff --git a/Sofa/framework/Type/src/sofa/type/RGBAColor.cpp b/Sofa/framework/Type/src/sofa/type/RGBAColor.cpp index 79c4aebe25a..2b51746e826 100644 --- a/Sofa/framework/Type/src/sofa/type/RGBAColor.cpp +++ b/Sofa/framework/Type/src/sofa/type/RGBAColor.cpp @@ -199,7 +199,8 @@ const std::map stringToColorMap { {"olive", g_olive}, {"maroon", g_maroon}, {"silver", g_silver}, - {"gold", g_gold} + {"gold", g_gold}, + {"azure", g_azure} }; SOFA_TYPE_API std::istream& operator>>(std::istream& i, RGBAColor& t) diff --git a/Sofa/framework/Type/src/sofa/type/RGBAColor.h b/Sofa/framework/Type/src/sofa/type/RGBAColor.h index af9aac7c0a0..2e68a2a63cd 100644 --- a/Sofa/framework/Type/src/sofa/type/RGBAColor.h +++ b/Sofa/framework/Type/src/sofa/type/RGBAColor.h @@ -90,6 +90,7 @@ class SOFA_TYPE_API RGBAColor constexpr static const RGBAColor& maroon(); constexpr static const RGBAColor& silver(); constexpr static const RGBAColor& gold(); + constexpr static const RGBAColor& azure(); /// @brief enlight a color by a given factor. static RGBAColor lighten(const RGBAColor& in, const SReal factor); @@ -270,6 +271,7 @@ constexpr RGBAColor g_olive { 0.5f, 0.5f, 0.0f, 1.0f }; constexpr RGBAColor g_maroon { 0.5f, 0.0f, 0.0f, 1.0f }; constexpr RGBAColor g_silver { 0.75f, 0.75f, 0.75f, 1.0f }; constexpr RGBAColor g_gold { 1.0f, 0.84f, 0.0f, 1.0f }; +constexpr RGBAColor g_azure { 0.0f, 0.5, 1.0f, 1.0f }; constexpr const RGBAColor& RGBAColor::white() { return g_white; } constexpr const RGBAColor& RGBAColor::black() { return g_black; } @@ -293,7 +295,7 @@ constexpr const RGBAColor& RGBAColor::olive() { return g_olive ; } constexpr const RGBAColor& RGBAColor::maroon() { return g_maroon; } constexpr const RGBAColor& RGBAColor::silver() { return g_silver; } constexpr const RGBAColor& RGBAColor::gold() { return g_gold ; } - +constexpr const RGBAColor& RGBAColor::azure() { return g_azure ; } } // namespace sofa::type From 253045758ed731eb7342ebe8b4b5470df0f43c98 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 20 Nov 2025 15:19:58 +0100 Subject: [PATCH 07/26] make drawSelection const --- Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp | 2 +- Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp index f1605162c45..36dc5bb89fe 100644 --- a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp +++ b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp @@ -341,7 +341,7 @@ void BaseViewer::fitObjectBBox(sofa::core::objectmodel::BaseObject * object) redraw(); } -void BaseViewer::drawSelection(sofa::core::visual::VisualParams* vparams) +void BaseViewer::drawSelection(sofa::core::visual::VisualParams* vparams) const { if (!m_enableSelectionDraw) return; diff --git a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h index 96812349250..7cc73589717 100644 --- a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h +++ b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h @@ -121,7 +121,7 @@ class SOFA_GUI_COMMON_API BaseViewer /// the rendering pass is done here (have to be called in a loop) virtual void drawScene(void) = 0; - void drawSelection(sofa::core::visual::VisualParams* vparams); + void drawSelection(sofa::core::visual::VisualParams* vparams) const; void setCurrentSelection(const std::set &selection); const std::set& getCurrentSelection() const; From 532fee6e44b01fb6d1ccb1f49882e4afdbb98615 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 20 Nov 2025 16:00:24 +0100 Subject: [PATCH 08/26] move drawing methods into functions that can be called elsewhere --- .../src/sofa/component/visual/VisualMesh.cpp | 155 +----------- .../src/sofa/component/visual/VisualMesh.h | 44 +--- Sofa/framework/Core/CMakeLists.txt | 2 + .../Core/src/sofa/core/visual/DrawMesh.cpp | 226 ++++++++++++++++++ .../Core/src/sofa/core/visual/DrawMesh.h | 94 ++++++++ 5 files changed, 333 insertions(+), 188 deletions(-) create mode 100644 Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp create mode 100644 Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp index 172e75fde15..7715756f38c 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp @@ -41,7 +41,6 @@ VisualMesh::VisualMesh() { } - void VisualMesh::init() { VisualModel::init(); @@ -57,150 +56,6 @@ void VisualMesh::init() } } -void VisualMesh::drawTriangles(helper::visual::DrawTool* drawTool) -{ - if (!l_topology) - return; - - const auto& elements = l_topology->getTriangles(); - - m_renderedPoints.resize(elements.size() * sofa::geometry::Triangle::NumberOfNodes); - - const auto elementSpace = d_elementSpace.getValue(); - const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); - - auto pointsIt = m_renderedPoints.begin(); - - for (sofa::Size i = 0; i < elements.size(); ++i) - { - const auto& element = elements[i]; - - const sofa::type::Vec3 center = elementCenter(positionAccessor.ref(), element); - - std::array facetsInElement{i}; - setPoints(facetsInElement, elements, positionAccessor.ref(), center, elementSpace, pointsIt); - } - - while (m_renderedColors.size() < elements.size() * sofa::geometry::Triangle::NumberOfNodes) - { - static constexpr std::array colors{ - type::makeHomogeneousArray( sofa::type::RGBAColor::green()), - type::makeHomogeneousArray(sofa::type::RGBAColor::teal()), - type::makeHomogeneousArray(sofa::type::RGBAColor::blue()), - }; - - const auto elementId = m_renderedColors.size() / sofa::geometry::Triangle::NumberOfNodes; - const auto triangleColor = colors[elementId % colors.size()]; - - m_renderedColors.insert(m_renderedColors.end(), triangleColor.begin(), triangleColor.end()); - } - - drawTool->drawTriangles(m_renderedPoints, m_renderedColors); -} - -namespace -{ -template -std::array -constexpr generateElementColors(const std::array& facetColors) -{ - std::array verticeColors; - auto verticeColorsIt = verticeColors.begin(); - for (const auto& c : facetColors) - { - for (std::size_t i = 0; i < NumberVerticesInFacet; ++i) - { - *verticeColorsIt++ = c; - } - } - return verticeColors; -} -} - -void VisualMesh::drawTetrahedra(helper::visual::DrawTool* drawTool) -{ - if (!l_topology) - return; - - const auto& elements = l_topology->getTetrahedra(); - const auto& facets = l_topology->getTriangles(); - - static constexpr std::size_t NumberTrianglesInTetrahedron = 4; - m_renderedPoints.resize(elements.size() * NumberTrianglesInTetrahedron * sofa::geometry::Triangle::NumberOfNodes); - - const auto elementSpace = d_elementSpace.getValue(); - const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); - - auto pointsIt = m_renderedPoints.begin(); - - for (sofa::Size i = 0; i < elements.size(); ++i) - { - const auto& element = elements[i]; - const auto& facetsInElement = l_topology->getTrianglesInTetrahedron(i); - assert(facetsInElement.size() == NumberTrianglesInTetrahedron); - - const sofa::type::Vec3 center = elementCenter(positionAccessor.ref(), element); - - setPoints(facetsInElement, facets, positionAccessor.ref(), center, elementSpace, pointsIt); - } - - while (m_renderedColors.size() < elements.size() * NumberTrianglesInTetrahedron * sofa::geometry::Triangle::NumberOfNodes) - { - static constexpr std::array colors = generateElementColors({ - sofa::type::RGBAColor::blue(), - sofa::type::RGBAColor::black(), - sofa::type::RGBAColor::azure(), - sofa::type::RGBAColor::cyan()}); - - m_renderedColors.insert(m_renderedColors.end(), colors.begin(), colors.end()); - } - - drawTool->drawTriangles(m_renderedPoints, m_renderedColors); -} - -void VisualMesh::drawHexahedra(helper::visual::DrawTool* drawTool) -{ - if (!l_topology) - return; - - const auto& elements = l_topology->getHexahedra(); - const auto& facets = l_topology->getQuads(); - - static constexpr std::size_t NumberQuadsInHexahedron = 6; - m_renderedPoints.resize(elements.size() * NumberQuadsInHexahedron * sofa::geometry::Quad::NumberOfNodes); - - const auto elementSpace = d_elementSpace.getValue(); - const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); - - auto pointsIt = m_renderedPoints.begin(); - - for (sofa::Size i = 0; i < elements.size(); ++i) - { - const auto& element = elements[i]; - const auto& facetsInElement = l_topology->getQuadsInHexahedron(i); - assert(facetsInElement.size() == NumberQuadsInHexahedron); - - const sofa::type::Vec3 center = elementCenter(positionAccessor.ref(), element); - - setPoints(facetsInElement, facets, positionAccessor.ref(), center, elementSpace, pointsIt); - } - - while (m_renderedColors.size() < elements.size() * NumberQuadsInHexahedron * sofa::geometry::Quad::NumberOfNodes) - { - static constexpr std::array colors = generateElementColors({ - sofa::type::RGBAColor(0.7f,0.7f,0.1f,1.f), - sofa::type::RGBAColor(0.7f,0.0f,0.0f,1.f), - sofa::type::RGBAColor(0.0f,0.7f,0.0f,1.f), - sofa::type::RGBAColor(0.0f,0.0f,0.7f,1.f), - sofa::type::RGBAColor(0.1f,0.7f,0.7f,1.f), - sofa::type::RGBAColor(0.7f,0.1f,0.7f,1.f)}); - - m_renderedColors.insert(m_renderedColors.end(), colors.begin(), colors.end()); - } - - drawTool->drawQuads(m_renderedPoints, m_renderedColors); -} - void VisualMesh::doDrawVisual(const core::visual::VisualParams* vparams) { auto* drawTool = vparams->drawTool(); @@ -210,12 +65,16 @@ void VisualMesh::doDrawVisual(const core::visual::VisualParams* vparams) const auto hasTetra = l_topology && !l_topology->getTetrahedra().empty(); const auto hasHexa = l_topology && !l_topology->getHexahedra().empty(); + const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); + + m_drawMesh.setElementSpace(d_elementSpace.getValue()); + if (!hasTetra && !hasHexa) { - drawTriangles(drawTool); + m_drawMesh.drawTriangles(drawTool, positionAccessor.ref(), l_topology.get()); } - drawTetrahedra(drawTool); - drawHexahedra(drawTool); + m_drawMesh.drawTetrahedra(drawTool, positionAccessor.ref(), l_topology.get()); + m_drawMesh.drawHexahedra(drawTool, positionAccessor.ref(), l_topology.get()); } void VisualMesh::validateTopology() diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h index c73e380bc85..ba7c447f30c 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.h @@ -21,8 +21,9 @@ ******************************************************************************/ #pragma once #include -#include #include +#include +#include namespace sofa::component::visual { @@ -39,54 +40,17 @@ class VisualMesh : public core::visual::VisualModel sofa::SingleLink l_topology; - void init() override; protected: VisualMesh(); - void drawTriangles(helper::visual::DrawTool* drawTool); - void drawTetrahedra(helper::visual::DrawTool* drawTool); - void drawHexahedra(helper::visual::DrawTool* drawTool); void doDrawVisual(const core::visual::VisualParams* vparams) override; - void validateTopology(); + core::visual::DrawMesh m_drawMesh; - sofa::type::vector< sofa::type::Vec3 > m_renderedPoints; - sofa::type::vector< sofa::type::RGBAColor > m_renderedColors; - - template - sofa::type::Vec3 elementCenter(const type::vector& position, const ElementType& element) - { - sofa::type::Vec3 center{}; - for (sofa::Size vId = 0; vId < element.size(); ++vId) - { - center += position[element[vId]]; - } - center /= element.size(); - return center; - } - - template - void setPoints( - const std::array facetsInElement, - const sofa::type::vector& facets, - const type::vector& position, - const type::Vec3& elementCenter, - SReal elementSpace, - sofa::type::vector< sofa::type::Vec3 >::iterator& pointsIt - ) - { - for (const auto& facetId : facetsInElement) - { - const auto& facet = facets[facetId]; - for (const auto vId : facet) - { - *pointsIt++ = (position[vId] - elementCenter) * (1._sreal - elementSpace) + elementCenter; - } - } - } + void validateTopology(); }; } diff --git a/Sofa/framework/Core/CMakeLists.txt b/Sofa/framework/Core/CMakeLists.txt index e28798a6ade..4de5aa87e99 100644 --- a/Sofa/framework/Core/CMakeLists.txt +++ b/Sofa/framework/Core/CMakeLists.txt @@ -210,6 +210,7 @@ set(HEADER_FILES ${SRC_ROOT}/visual/BaseVisualStyle.h ${SRC_ROOT}/visual/Data[DisplayFlags].h ${SRC_ROOT}/visual/DisplayFlags.h + ${SRC_ROOT}/visual/DrawMesh.h ${SRC_ROOT}/visual/FlagTreeItem.h ${SRC_ROOT}/visual/Shader.h ${SRC_ROOT}/visual/Tristate.h @@ -342,6 +343,7 @@ set(SOURCE_FILES ${SRC_ROOT}/topology/TopologySubsetIndices.cpp ${SRC_ROOT}/visual/Data[DisplayFlags].cpp ${SRC_ROOT}/visual/DisplayFlags.cpp + ${SRC_ROOT}/visual/DrawMesh.cpp ${SRC_ROOT}/visual/FlagTreeItem.cpp ${SRC_ROOT}/visual/Shader.cpp ${SRC_ROOT}/visual/VisualLoop.cpp diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp new file mode 100644 index 00000000000..78ba8667803 --- /dev/null +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp @@ -0,0 +1,226 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2006 INRIA, USTL, UJF, CNRS, MGH * +* * +* This program 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 program 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 program. If not, see . * +******************************************************************************* +* Authors: The SOFA Team and external contributors (see Authors.txt) * +* * +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#include + +namespace sofa::core::visual +{ + +namespace +{ + +template +sofa::type::Vec3 elementCenter(const type::vector& position, const ElementType& element) +{ + sofa::type::Vec3 center{}; + for (sofa::Size vId = 0; vId < element.size(); ++vId) + { + center += position[element[vId]]; + } + center /= element.size(); + return center; +} + +template +void setPoints( + const std::array facetsInElement, + const sofa::type::vector& facets, + const type::vector& position, + const type::Vec3& elementCenter, + SReal elementSpace, + sofa::type::vector< sofa::type::Vec3 >::iterator& pointsIt + ) +{ + for (const auto& facetId : facetsInElement) + { + const auto& facet = facets[facetId]; + for (const auto vId : facet) + { + *pointsIt++ = (position[vId] - elementCenter) * (1._sreal - elementSpace) + elementCenter; + } + } +} + +template +std::array +constexpr generateElementColors(const std::array& facetColors) +{ + std::array verticeColors; + auto verticeColorsIt = verticeColors.begin(); + for (const auto& c : facetColors) + { + for (std::size_t i = 0; i < NumberVerticesInFacet; ++i) + { + *verticeColorsIt++ = c; + } + } + return verticeColors; +} + +} + +void DrawMesh::drawTriangles( + sofa::helper::visual::DrawTool* drawTool, const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) +{ + m_drawTriangleMesh.draw(drawTool, position, topology); +} + +void DrawMesh::drawTetrahedra(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) +{ + m_drawTetrahedronMesh.draw(drawTool, position, topology); +} + +void DrawMesh::drawHexahedra(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) +{ + m_drawHexahedronMesh.draw(drawTool, position, topology); +} + +void DrawMesh::setElementSpace(SReal elementSpace) +{ + m_drawTriangleMesh.elementSpace = + m_drawTetrahedronMesh.elementSpace = + m_drawHexahedronMesh.elementSpace = elementSpace; +} + +void DrawElementMesh::draw( + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) +{ + if (!topology) + return; + + const auto& elements = topology->getTriangles(); + + renderedPoints.resize(elements.size() * sofa::geometry::Triangle::NumberOfNodes); + + auto pointsIt = renderedPoints.begin(); + + for (sofa::Size i = 0; i < elements.size(); ++i) + { + const auto& element = elements[i]; + + const sofa::type::Vec3 center = elementCenter(position, element); + + std::array facetsInElement{i}; + setPoints(facetsInElement, elements, position, center, elementSpace, pointsIt); + } + + while (renderedColors.size() < elements.size() * sofa::geometry::Triangle::NumberOfNodes) + { + static constexpr std::array colors{ + type::makeHomogeneousArray( sofa::type::RGBAColor::green()), + type::makeHomogeneousArray(sofa::type::RGBAColor::teal()), + type::makeHomogeneousArray(sofa::type::RGBAColor::blue()), + }; + + const auto elementId = renderedColors.size() / sofa::geometry::Triangle::NumberOfNodes; + const auto triangleColor = colors[elementId % colors.size()]; + + renderedColors.insert(renderedColors.end(), triangleColor.begin(), triangleColor.end()); + } + + drawTool->drawTriangles(renderedPoints, renderedColors); +} + +void DrawElementMesh::draw(sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) +{ + if (!topology) + return; + + const auto& elements = topology->getTetrahedra(); + const auto& facets = topology->getTriangles(); + + static constexpr std::size_t NumberTrianglesInTetrahedron = 4; + renderedPoints.resize(elements.size() * NumberTrianglesInTetrahedron * sofa::geometry::Triangle::NumberOfNodes); + + auto pointsIt = renderedPoints.begin(); + + for (sofa::Size i = 0; i < elements.size(); ++i) + { + const auto& element = elements[i]; + const auto& facetsInElement = topology->getTrianglesInTetrahedron(i); + assert(facetsInElement.size() == NumberTrianglesInTetrahedron); + + const sofa::type::Vec3 center = elementCenter(position, element); + + setPoints(facetsInElement, facets, position, center, elementSpace, pointsIt); + } + + while (renderedColors.size() < elements.size() * NumberTrianglesInTetrahedron * sofa::geometry::Triangle::NumberOfNodes) + { + static constexpr std::array colors = generateElementColors({ + sofa::type::RGBAColor::blue(), + sofa::type::RGBAColor::black(), + sofa::type::RGBAColor::azure(), + sofa::type::RGBAColor::cyan()}); + + renderedColors.insert(renderedColors.end(), colors.begin(), colors.end()); + } + + drawTool->drawTriangles(renderedPoints, renderedColors); +} +void DrawElementMesh::draw(sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) +{ + if (!topology) + return; + + const auto& elements = topology->getHexahedra(); + const auto& facets = topology->getQuads(); + + static constexpr std::size_t NumberQuadsInHexahedron = 6; + renderedPoints.resize(elements.size() * NumberQuadsInHexahedron * sofa::geometry::Quad::NumberOfNodes); + + auto pointsIt = renderedPoints.begin(); + + for (sofa::Size i = 0; i < elements.size(); ++i) + { + const auto& element = elements[i]; + const auto& facetsInElement = topology->getQuadsInHexahedron(i); + assert(facetsInElement.size() == NumberQuadsInHexahedron); + + const sofa::type::Vec3 center = elementCenter(position, element); + + setPoints(facetsInElement, facets, position, center, elementSpace, pointsIt); + } + + while (renderedColors.size() < elements.size() * NumberQuadsInHexahedron * sofa::geometry::Quad::NumberOfNodes) + { + static constexpr std::array colors = generateElementColors({ + sofa::type::RGBAColor(0.7f,0.7f,0.1f,1.f), + sofa::type::RGBAColor(0.7f,0.0f,0.0f,1.f), + sofa::type::RGBAColor(0.0f,0.7f,0.0f,1.f), + sofa::type::RGBAColor(0.0f,0.0f,0.7f,1.f), + sofa::type::RGBAColor(0.1f,0.7f,0.7f,1.f), + sofa::type::RGBAColor(0.7f,0.1f,0.7f,1.f)}); + + renderedColors.insert(renderedColors.end(), colors.begin(), colors.end()); + } + + drawTool->drawQuads(renderedPoints, renderedColors); +} + +} // namespace sofa::core::visual diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h new file mode 100644 index 00000000000..38b8c61f08d --- /dev/null +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -0,0 +1,94 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2006 INRIA, USTL, UJF, CNRS, MGH * +* * +* This program 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 program 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 program. If not, see . * +******************************************************************************* +* Authors: The SOFA Team and external contributors (see Authors.txt) * +* * +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#pragma once + +#include +#include +#include +#include + +namespace sofa::core::visual +{ + +struct SOFA_CORE_API BaseDrawMesh +{ + virtual ~BaseDrawMesh() = default; + + sofa::type::vector< sofa::type::Vec3 > renderedPoints; + sofa::type::vector< sofa::type::RGBAColor > renderedColors; + + SReal elementSpace { 0.125_sreal }; + + virtual void draw( + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) = 0; +}; + +template +struct DrawElementMesh{}; + +template<> +struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh +{ + void draw( + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) override; +}; + +template<> +struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh +{ + void draw( + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) override; +}; + +template<> +struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh +{ + void draw( + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) override; +}; + +class SOFA_CORE_API DrawMesh +{ +public: + + void drawTriangles(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); + void drawTetrahedra(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); + void drawHexahedra(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); + + void setElementSpace(SReal elementSpace); + + private: + + DrawElementMesh m_drawTriangleMesh; + DrawElementMesh m_drawTetrahedronMesh; + DrawElementMesh m_drawHexahedronMesh; +}; + +} // namespace sofa::core::visual From 445de0aca8ccb73130fa77c80e831c1b8ae8f0fa Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 20 Nov 2025 16:41:10 +0100 Subject: [PATCH 09/26] draw mesh from the viewer --- .../Common/src/sofa/gui/common/BaseViewer.cpp | 49 +++++++++++------ .../Common/src/sofa/gui/common/BaseViewer.h | 15 +++-- .../Core/src/sofa/core/visual/DrawMesh.cpp | 55 ++++++++++++++++++- .../Core/src/sofa/core/visual/DrawMesh.h | 20 +++++-- 4 files changed, 107 insertions(+), 32 deletions(-) diff --git a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp index 36dc5bb89fe..59f013e468c 100644 --- a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp +++ b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp @@ -341,7 +341,7 @@ void BaseViewer::fitObjectBBox(sofa::core::objectmodel::BaseObject * object) redraw(); } -void BaseViewer::drawSelection(sofa::core::visual::VisualParams* vparams) const +void BaseViewer::drawSelection(sofa::core::visual::VisualParams* vparams) { if (!m_enableSelectionDraw) return; @@ -427,32 +427,47 @@ void BaseViewer::drawSelection(sofa::core::visual::VisualParams* vparams) const if(m_showSelectedObjectSurfaces && !positions.empty()) { - auto triangles = object->findData("triangles"); - if(triangles) + if (const auto topology = object->toBaseMeshTopology()) { - auto d_triangles = dynamic_cast>*>(triangles); - if(d_triangles) + m_drawMeshContainer[object].drawSurface(drawTool, positions, topology); + } + else + { + auto triangles = object->findData("triangles"); + if(triangles) { - std::vector tripoints; - for(auto indices : d_triangles->getValue()) + auto d_triangles = dynamic_cast>*>(triangles); + if(d_triangles) { - if(indices[0] < positions.size() && - indices[1] < positions.size() && - indices[2] < positions.size()) + std::vector tripoints; + for(auto indices : d_triangles->getValue()) { - tripoints.push_back(positions[indices[0]]); - tripoints.push_back(positions[indices[1]]); - tripoints.push_back(positions[indices[1]]); - tripoints.push_back(positions[indices[2]]); - tripoints.push_back(positions[indices[2]]); - tripoints.push_back(positions[indices[0]]); + if(indices[0] < positions.size() && + indices[1] < positions.size() && + indices[2] < positions.size()) + { + tripoints.push_back(positions[indices[0]]); + tripoints.push_back(positions[indices[1]]); + tripoints.push_back(positions[indices[1]]); + tripoints.push_back(positions[indices[2]]); + tripoints.push_back(positions[indices[2]]); + tripoints.push_back(positions[indices[0]]); + } } + drawTool->drawLines(tripoints, size, m_selectionColor); } - drawTool->drawLines(tripoints, size, m_selectionColor); } } } + if(m_showSelectedObjectVolumes && !positions.empty()) + { + if (const auto topology = object->toBaseMeshTopology()) + { + m_drawMeshContainer[object].drawVolume(drawTool, positions, topology); + } + } + if(m_showSelectedObjectIndices && !positions.empty() && validBox) { const float scale = (box.maxBBox() - box.minBBox()).norm() * m_visualScaling; diff --git a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h index 7cc73589717..c4b593fada9 100644 --- a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h +++ b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h @@ -20,19 +20,17 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -#include - +#include +#include +#include +#include #include - +#include #include #include #include -#include -#include #include -#include - #include namespace sofa::component::setting @@ -121,7 +119,7 @@ class SOFA_GUI_COMMON_API BaseViewer /// the rendering pass is done here (have to be called in a loop) virtual void drawScene(void) = 0; - void drawSelection(sofa::core::visual::VisualParams* vparams) const; + void drawSelection(sofa::core::visual::VisualParams* vparams); void setCurrentSelection(const std::set &selection); const std::set& getCurrentSelection() const; @@ -174,6 +172,7 @@ class SOFA_GUI_COMMON_API BaseViewer std::string _screenshotDirectory; std::set currentSelection; + std::unordered_map m_drawMeshContainer; }; } // namespace sofa::gui::common diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp index 78ba8667803..5cb3d7cb683 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp @@ -101,7 +101,56 @@ void DrawMesh::setElementSpace(SReal elementSpace) m_drawHexahedronMesh.elementSpace = elementSpace; } -void DrawElementMesh::draw( +void DrawMesh::drawSurface(sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) +{ + drawTriangles(drawTool, position, topology); +} + +void DrawMesh::drawVolume(sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) +{ + drawTetrahedra(drawTool, position, topology); + drawHexahedra(drawTool, position, topology); +} + +void DrawMesh::draw(sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) +{ + if (!topology) + { + return; + } + + const auto hasTetra = topology && !topology->getTetrahedra().empty(); + const auto hasHexa = topology && !topology->getHexahedra().empty(); + + if (!hasTetra && !hasHexa) + { + drawSurface(drawTool, position, topology); + } + drawVolume(drawTool, position, topology); +} + +void BaseDrawMesh::draw(sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) +{ + if (!drawTool) + return; + if (!topology) + return; + + const auto stateLifeCycle = drawTool->makeStateLifeCycle(); + drawTool->disableLighting(); + + doDraw(drawTool, position, topology); +} + +void DrawElementMesh::doDraw( sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) @@ -142,7 +191,7 @@ void DrawElementMesh::draw( drawTool->drawTriangles(renderedPoints, renderedColors); } -void DrawElementMesh::draw(sofa::helper::visual::DrawTool* drawTool, +void DrawElementMesh::doDraw(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) { @@ -181,7 +230,7 @@ void DrawElementMesh::draw(sofa::helper::visual::DrawTool drawTool->drawTriangles(renderedPoints, renderedColors); } -void DrawElementMesh::draw(sofa::helper::visual::DrawTool* drawTool, +void DrawElementMesh::doDraw(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) { diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index 38b8c61f08d..edad9ff8245 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -38,7 +38,14 @@ struct SOFA_CORE_API BaseDrawMesh SReal elementSpace { 0.125_sreal }; - virtual void draw( + void draw( + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology); + +protected: + + virtual void doDraw( sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) = 0; @@ -50,7 +57,7 @@ struct DrawElementMesh{}; template<> struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh { - void draw( + void doDraw( sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) override; @@ -59,7 +66,7 @@ struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh template<> struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh { - void draw( + void doDraw( sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) override; @@ -68,7 +75,7 @@ struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh template<> struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh { - void draw( + void doDraw( sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) override; @@ -84,6 +91,11 @@ class SOFA_CORE_API DrawMesh void setElementSpace(SReal elementSpace); + void drawSurface(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); + void drawVolume(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); + + void draw(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); + private: DrawElementMesh m_drawTriangleMesh; From 8ddd723f348043c5990b5f11e095cce505f07c4d Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 20 Nov 2025 19:37:50 +0100 Subject: [PATCH 10/26] missing position --- examples/Component/Visual/VisualMesh.scn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Component/Visual/VisualMesh.scn b/examples/Component/Visual/VisualMesh.scn index bb08e1792b1..7a67077d6a8 100644 --- a/examples/Component/Visual/VisualMesh.scn +++ b/examples/Component/Visual/VisualMesh.scn @@ -8,7 +8,7 @@ - + From ca45b15f4c689a142e9640b9d1664f23df2f8cec Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 21 Nov 2025 11:05:06 +0100 Subject: [PATCH 11/26] implement CRTP --- .../Core/src/sofa/core/visual/DrawMesh.cpp | 178 +++++++----------- .../Core/src/sofa/core/visual/DrawMesh.h | 87 +++++++-- 2 files changed, 133 insertions(+), 132 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp index 5cb3d7cb683..da8c4f89939 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp @@ -39,57 +39,30 @@ sofa::type::Vec3 elementCenter(const type::vector& position, const E return center; } -template -void setPoints( - const std::array facetsInElement, - const sofa::type::vector& facets, - const type::vector& position, - const type::Vec3& elementCenter, - SReal elementSpace, - sofa::type::vector< sofa::type::Vec3 >::iterator& pointsIt - ) -{ - for (const auto& facetId : facetsInElement) - { - const auto& facet = facets[facetId]; - for (const auto vId : facet) - { - *pointsIt++ = (position[vId] - elementCenter) * (1._sreal - elementSpace) + elementCenter; - } - } -} +} // namespace -template -std::array -constexpr generateElementColors(const std::array& facetColors) -{ - std::array verticeColors; - auto verticeColorsIt = verticeColors.begin(); - for (const auto& c : facetColors) - { - for (std::size_t i = 0; i < NumberVerticesInFacet; ++i) - { - *verticeColorsIt++ = c; - } - } - return verticeColors; -} -} void DrawMesh::drawTriangles( - sofa::helper::visual::DrawTool* drawTool, const type::vector& position, + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) { m_drawTriangleMesh.draw(drawTool, position, topology); } -void DrawMesh::drawTetrahedra(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) +void DrawMesh::drawTetrahedra( + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) { m_drawTetrahedronMesh.draw(drawTool, position, topology); } -void DrawMesh::drawHexahedra(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) +void DrawMesh::drawHexahedra( + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology) { m_drawHexahedronMesh.draw(drawTool, position, topology); } @@ -135,34 +108,22 @@ void DrawMesh::draw(sofa::helper::visual::DrawTool* drawTool, drawVolume(drawTool, position, topology); } -void BaseDrawMesh::draw(sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) -{ - if (!drawTool) - return; - if (!topology) - return; - - const auto stateLifeCycle = drawTool->makeStateLifeCycle(); - drawTool->disableLighting(); - - doDraw(drawTool, position, topology); -} - -void DrawElementMesh::doDraw( +void DrawElementMesh::doDraw( sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology, + const ColorContainer& colors) { if (!topology) return; const auto& elements = topology->getTriangles(); - renderedPoints.resize(elements.size() * sofa::geometry::Triangle::NumberOfNodes); - - auto pointsIt = renderedPoints.begin(); + const auto size = (elements.size() / NumberColors) * sofa::geometry::Triangle::NumberOfNodes; + for ( auto& p : renderedPoints) + { + p.resize(size); + } for (sofa::Size i = 0; i < elements.size(); ++i) { @@ -170,30 +131,23 @@ void DrawElementMesh::doDraw( const sofa::type::Vec3 center = elementCenter(position, element); - std::array facetsInElement{i}; - setPoints(facetsInElement, elements, position, center, elementSpace, pointsIt); + for (std::size_t j = 0; j < sofa::geometry::Triangle::NumberOfNodes; ++j) + { + renderedPoints[i % NumberColors][i / NumberColors + j] = applyElementSpace(position[element[j]], center); + } } - while (renderedColors.size() < elements.size() * sofa::geometry::Triangle::NumberOfNodes) + for (std::size_t j = 0; j < NumberColors; ++j) { - static constexpr std::array colors{ - type::makeHomogeneousArray( sofa::type::RGBAColor::green()), - type::makeHomogeneousArray(sofa::type::RGBAColor::teal()), - type::makeHomogeneousArray(sofa::type::RGBAColor::blue()), - }; - - const auto elementId = renderedColors.size() / sofa::geometry::Triangle::NumberOfNodes; - const auto triangleColor = colors[elementId % colors.size()]; - - renderedColors.insert(renderedColors.end(), triangleColor.begin(), triangleColor.end()); + drawTool->drawTriangles(renderedPoints[j], colors[j]); } - - drawTool->drawTriangles(renderedPoints, renderedColors); } -void DrawElementMesh::doDraw(sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) +void DrawElementMesh::doDraw( + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology, + const ColorContainer& colors) { if (!topology) return; @@ -201,11 +155,12 @@ void DrawElementMesh::doDraw(sofa::helper::visual::DrawTo const auto& elements = topology->getTetrahedra(); const auto& facets = topology->getTriangles(); - static constexpr std::size_t NumberTrianglesInTetrahedron = 4; - renderedPoints.resize(elements.size() * NumberTrianglesInTetrahedron * sofa::geometry::Triangle::NumberOfNodes); - - auto pointsIt = renderedPoints.begin(); + for ( auto& p : renderedPoints) + { + p.resize(elements.size() * sofa::geometry::Triangle::NumberOfNodes); + } + std::size_t renderedPointId {}; for (sofa::Size i = 0; i < elements.size(); ++i) { const auto& element = elements[i]; @@ -214,25 +169,26 @@ void DrawElementMesh::doDraw(sofa::helper::visual::DrawTo const sofa::type::Vec3 center = elementCenter(position, element); - setPoints(facetsInElement, facets, position, center, elementSpace, pointsIt); + for (std::size_t j = 0; j < NumberTrianglesInTetrahedron; ++j) + { + const auto faceId = facetsInElement[j]; + for (const auto vertexId : facets[faceId]) + { + renderedPoints[j][renderedPointId++] = applyElementSpace(position[vertexId], center); + } + } } - while (renderedColors.size() < elements.size() * NumberTrianglesInTetrahedron * sofa::geometry::Triangle::NumberOfNodes) + for (std::size_t j = 0; j < NumberTrianglesInTetrahedron; ++j) { - static constexpr std::array colors = generateElementColors({ - sofa::type::RGBAColor::blue(), - sofa::type::RGBAColor::black(), - sofa::type::RGBAColor::azure(), - sofa::type::RGBAColor::cyan()}); - - renderedColors.insert(renderedColors.end(), colors.begin(), colors.end()); + drawTool->drawTriangles(renderedPoints[j], colors[j]); } - - drawTool->drawTriangles(renderedPoints, renderedColors); } + void DrawElementMesh::doDraw(sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology, + const ColorContainer& colors) { if (!topology) return; @@ -240,36 +196,34 @@ void DrawElementMesh::doDraw(sofa::helper::visual::DrawToo const auto& elements = topology->getHexahedra(); const auto& facets = topology->getQuads(); - static constexpr std::size_t NumberQuadsInHexahedron = 6; - renderedPoints.resize(elements.size() * NumberQuadsInHexahedron * sofa::geometry::Quad::NumberOfNodes); - - auto pointsIt = renderedPoints.begin(); + for ( auto& p : renderedPoints) + { + p.resize(elements.size() * sofa::geometry::Quad::NumberOfNodes); + } + std::size_t renderedPointId {}; for (sofa::Size i = 0; i < elements.size(); ++i) { const auto& element = elements[i]; const auto& facetsInElement = topology->getQuadsInHexahedron(i); - assert(facetsInElement.size() == NumberQuadsInHexahedron); + assert(facetsInElement.size() == NumberTrianglesInTetrahedron); const sofa::type::Vec3 center = elementCenter(position, element); - setPoints(facetsInElement, facets, position, center, elementSpace, pointsIt); + for (std::size_t j = 0; j < NumberQuadsInHexahedron; ++j) + { + const auto faceId = facetsInElement[j]; + for (const auto vertexId : facets[faceId]) + { + renderedPoints[j][renderedPointId++] = applyElementSpace(position[vertexId], center); + } + } } - while (renderedColors.size() < elements.size() * NumberQuadsInHexahedron * sofa::geometry::Quad::NumberOfNodes) + for (std::size_t j = 0; j < NumberQuadsInHexahedron; ++j) { - static constexpr std::array colors = generateElementColors({ - sofa::type::RGBAColor(0.7f,0.7f,0.1f,1.f), - sofa::type::RGBAColor(0.7f,0.0f,0.0f,1.f), - sofa::type::RGBAColor(0.0f,0.7f,0.0f,1.f), - sofa::type::RGBAColor(0.0f,0.0f,0.7f,1.f), - sofa::type::RGBAColor(0.1f,0.7f,0.7f,1.f), - sofa::type::RGBAColor(0.7f,0.1f,0.7f,1.f)}); - - renderedColors.insert(renderedColors.end(), colors.begin(), colors.end()); + drawTool->drawTriangles(renderedPoints[j], colors[j]); } - - drawTool->drawQuads(renderedPoints, renderedColors); } } // namespace sofa::core::visual diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index edad9ff8245..b4a092d80dd 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -29,56 +29,103 @@ namespace sofa::core::visual { -struct SOFA_CORE_API BaseDrawMesh +template +struct BaseDrawMesh { - virtual ~BaseDrawMesh() = default; - - sofa::type::vector< sofa::type::Vec3 > renderedPoints; - sofa::type::vector< sofa::type::RGBAColor > renderedColors; + using ColorContainer = std::array; SReal elementSpace { 0.125_sreal }; void draw( sofa::helper::visual::DrawTool* drawTool, const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology); + sofa::core::topology::BaseMeshTopology* topology, + const ColorContainer& colors = Derived::defaultColors) + { + if (!drawTool) + return; + if (!topology) + return; -protected: + const auto stateLifeCycle = drawTool->makeStateLifeCycle(); + drawTool->disableLighting(); - virtual void doDraw( - sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) = 0; + static_cast(*this)->doDraw(drawTool, position, topology, colors); + } + + sofa::type::Vec3 applyElementSpace(const sofa::type::Vec3& position, const sofa::type::Vec3& elementCenter) const + { + return (position - elementCenter) * (1._sreal - elementSpace) + elementCenter; + } + +protected: + std::array, Derived::NumberColors> renderedPoints; }; template struct DrawElementMesh{}; template<> -struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh +struct SOFA_CORE_API DrawElementMesh + : BaseDrawMesh> { + static constexpr std::size_t NumberColors = 3; + + static constexpr ColorContainer defaultColors { + sofa::type::RGBAColor::green(), + sofa::type::RGBAColor::teal(), + sofa::type::RGBAColor::blue() + }; + void doDraw( sofa::helper::visual::DrawTool* drawTool, const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) override; + sofa::core::topology::BaseMeshTopology* topology, + const ColorContainer& colors); }; template<> -struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh +struct SOFA_CORE_API DrawElementMesh + : BaseDrawMesh> { - void doDraw( - sofa::helper::visual::DrawTool* drawTool, + static constexpr std::size_t NumberTrianglesInTetrahedron = 4; + static constexpr std::size_t NumberColors = NumberTrianglesInTetrahedron; + + static constexpr ColorContainer defaultColors { + sofa::type::RGBAColor::blue(), + sofa::type::RGBAColor::black(), + sofa::type::RGBAColor::azure(), + sofa::type::RGBAColor::cyan() + }; + +private: + + void doDraw(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) override; + sofa::core::topology::BaseMeshTopology* topology, + const ColorContainer& colors); }; template<> -struct SOFA_CORE_API DrawElementMesh : BaseDrawMesh +struct SOFA_CORE_API DrawElementMesh + : BaseDrawMesh> { + static constexpr std::size_t NumberQuadsInHexahedron = 6; + static constexpr std::size_t NumberColors = NumberQuadsInHexahedron; + static constexpr ColorContainer defaultColors { + sofa::type::RGBAColor(0.7f,0.7f,0.1f,1.f), + sofa::type::RGBAColor(0.7f,0.0f,0.0f,1.f), + sofa::type::RGBAColor(0.0f,0.7f,0.0f,1.f), + sofa::type::RGBAColor(0.0f,0.0f,0.7f,1.f), + sofa::type::RGBAColor(0.1f,0.7f,0.7f,1.f), + sofa::type::RGBAColor(0.7f,0.1f,0.7f,1.f) + }; + void doDraw( sofa::helper::visual::DrawTool* drawTool, const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) override; + sofa::core::topology::BaseMeshTopology* topology, + const ColorContainer& colors); }; class SOFA_CORE_API DrawMesh @@ -96,7 +143,7 @@ class SOFA_CORE_API DrawMesh void draw(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); - private: +private: DrawElementMesh m_drawTriangleMesh; DrawElementMesh m_drawTetrahedronMesh; From 78f9e400322ccd36573271244fbd8844b3193442 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 21 Nov 2025 11:38:59 +0100 Subject: [PATCH 12/26] fix --- .../Core/src/sofa/core/visual/DrawMesh.h | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index b4a092d80dd..f4b8c8b4545 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -29,10 +29,11 @@ namespace sofa::core::visual { -template +template struct BaseDrawMesh { - using ColorContainer = std::array; + static constexpr std::size_t NumberColors { NumberColors_ }; + using ColorContainer = std::array; SReal elementSpace { 0.125_sreal }; @@ -50,7 +51,7 @@ struct BaseDrawMesh const auto stateLifeCycle = drawTool->makeStateLifeCycle(); drawTool->disableLighting(); - static_cast(*this)->doDraw(drawTool, position, topology, colors); + static_cast(*this).doDraw(drawTool, position, topology, colors); } sofa::type::Vec3 applyElementSpace(const sofa::type::Vec3& position, const sofa::type::Vec3& elementCenter) const @@ -59,18 +60,17 @@ struct BaseDrawMesh } protected: - std::array, Derived::NumberColors> renderedPoints; + std::array, NumberColors> renderedPoints; }; template -struct DrawElementMesh{}; +class DrawElementMesh{}; template<> -struct SOFA_CORE_API DrawElementMesh - : BaseDrawMesh> +class SOFA_CORE_API DrawElementMesh + : public BaseDrawMesh, 3> { - static constexpr std::size_t NumberColors = 3; - + friend BaseDrawMesh; static constexpr ColorContainer defaultColors { sofa::type::RGBAColor::green(), sofa::type::RGBAColor::teal(), @@ -85,11 +85,11 @@ struct SOFA_CORE_API DrawElementMesh }; template<> -struct SOFA_CORE_API DrawElementMesh - : BaseDrawMesh> +class SOFA_CORE_API DrawElementMesh + : public BaseDrawMesh, 4> { + friend BaseDrawMesh; static constexpr std::size_t NumberTrianglesInTetrahedron = 4; - static constexpr std::size_t NumberColors = NumberTrianglesInTetrahedron; static constexpr ColorContainer defaultColors { sofa::type::RGBAColor::blue(), @@ -98,8 +98,6 @@ struct SOFA_CORE_API DrawElementMesh sofa::type::RGBAColor::cyan() }; -private: - void doDraw(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology, @@ -107,11 +105,12 @@ struct SOFA_CORE_API DrawElementMesh }; template<> -struct SOFA_CORE_API DrawElementMesh - : BaseDrawMesh> +class SOFA_CORE_API DrawElementMesh + : public BaseDrawMesh, 6> { + friend BaseDrawMesh; static constexpr std::size_t NumberQuadsInHexahedron = 6; - static constexpr std::size_t NumberColors = NumberQuadsInHexahedron; + static constexpr ColorContainer defaultColors { sofa::type::RGBAColor(0.7f,0.7f,0.1f,1.f), sofa::type::RGBAColor(0.7f,0.0f,0.0f,1.f), From 32b5cfa02b8b49a36c48580bffeb062e6c649d53 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 21 Nov 2025 13:28:41 +0100 Subject: [PATCH 13/26] fix --- .../src/sofa/component/visual/VisualMesh.cpp | 11 +--- .../Core/src/sofa/core/visual/DrawMesh.cpp | 51 +++++-------------- .../Core/src/sofa/core/visual/DrawMesh.h | 35 ++++++++----- 3 files changed, 37 insertions(+), 60 deletions(-) diff --git a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp index 7715756f38c..ebe816f329c 100644 --- a/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp +++ b/Sofa/Component/Visual/src/sofa/component/visual/VisualMesh.cpp @@ -62,19 +62,10 @@ void VisualMesh::doDrawVisual(const core::visual::VisualParams* vparams) vparams->drawTool()->disableLighting(); - const auto hasTetra = l_topology && !l_topology->getTetrahedra().empty(); - const auto hasHexa = l_topology && !l_topology->getHexahedra().empty(); - const auto& positionAccessor = sofa::helper::getReadAccessor(d_position); m_drawMesh.setElementSpace(d_elementSpace.getValue()); - - if (!hasTetra && !hasHexa) - { - m_drawMesh.drawTriangles(drawTool, positionAccessor.ref(), l_topology.get()); - } - m_drawMesh.drawTetrahedra(drawTool, positionAccessor.ref(), l_topology.get()); - m_drawMesh.drawHexahedra(drawTool, positionAccessor.ref(), l_topology.get()); + m_drawMesh.draw(drawTool, positionAccessor.ref(), l_topology.get()); } void VisualMesh::validateTopology() diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp index da8c4f89939..1435581c05f 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp @@ -41,52 +41,24 @@ sofa::type::Vec3 elementCenter(const type::vector& position, const E } // namespace - - -void DrawMesh::drawTriangles( - sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) -{ - m_drawTriangleMesh.draw(drawTool, position, topology); -} - -void DrawMesh::drawTetrahedra( - sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) -{ - m_drawTetrahedronMesh.draw(drawTool, position, topology); -} - -void DrawMesh::drawHexahedra( - sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) -{ - m_drawHexahedronMesh.draw(drawTool, position, topology); -} - void DrawMesh::setElementSpace(SReal elementSpace) { - m_drawTriangleMesh.elementSpace = - m_drawTetrahedronMesh.elementSpace = - m_drawHexahedronMesh.elementSpace = elementSpace; + std::apply([elementSpace](auto&&... mesh){ ((mesh.elementSpace = elementSpace), ...); }, m_meshes); } void DrawMesh::drawSurface(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) { - drawTriangles(drawTool, position, topology); + drawElements(drawTool, position, topology); } void DrawMesh::drawVolume(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology) { - drawTetrahedra(drawTool, position, topology); - drawHexahedra(drawTool, position, topology); + drawElements(drawTool, position, topology); + drawElements(drawTool, position, topology); } void DrawMesh::draw(sofa::helper::visual::DrawTool* drawTool, @@ -119,12 +91,13 @@ void DrawElementMesh::doDraw( const auto& elements = topology->getTriangles(); - const auto size = (elements.size() / NumberColors) * sofa::geometry::Triangle::NumberOfNodes; + const auto size = (elements.size() / NumberColors + 1) * sofa::geometry::Triangle::NumberOfNodes; for ( auto& p : renderedPoints) { p.resize(size); } + std::array renderedPointId {}; for (sofa::Size i = 0; i < elements.size(); ++i) { const auto& element = elements[i]; @@ -133,7 +106,7 @@ void DrawElementMesh::doDraw( for (std::size_t j = 0; j < sofa::geometry::Triangle::NumberOfNodes; ++j) { - renderedPoints[i % NumberColors][i / NumberColors + j] = applyElementSpace(position[element[j]], center); + renderedPoints[i % NumberColors][renderedPointId[i%NumberColors]++] = applyElementSpace(position[element[j]], center); } } @@ -172,9 +145,11 @@ void DrawElementMesh::doDraw( for (std::size_t j = 0; j < NumberTrianglesInTetrahedron; ++j) { const auto faceId = facetsInElement[j]; + std::size_t k {}; for (const auto vertexId : facets[faceId]) { - renderedPoints[j][renderedPointId++] = applyElementSpace(position[vertexId], center); + renderedPoints[j][i * sofa::geometry::Triangle::NumberOfNodes + k] = applyElementSpace(position[vertexId], center); + ++k; } } } @@ -213,16 +188,18 @@ void DrawElementMesh::doDraw(sofa::helper::visual::DrawToo for (std::size_t j = 0; j < NumberQuadsInHexahedron; ++j) { const auto faceId = facetsInElement[j]; + std::size_t k {}; for (const auto vertexId : facets[faceId]) { - renderedPoints[j][renderedPointId++] = applyElementSpace(position[vertexId], center); + renderedPoints[j][i * sofa::geometry::Quad::NumberOfNodes + k] = applyElementSpace(position[vertexId], center); + ++k; } } } for (std::size_t j = 0; j < NumberQuadsInHexahedron; ++j) { - drawTool->drawTriangles(renderedPoints[j], colors[j]); + drawTool->drawQuads(renderedPoints[j], colors[j]); } } diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index f4b8c8b4545..67cbf95df0d 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -54,20 +54,19 @@ struct BaseDrawMesh static_cast(*this).doDraw(drawTool, position, topology, colors); } +protected: sofa::type::Vec3 applyElementSpace(const sofa::type::Vec3& position, const sofa::type::Vec3& elementCenter) const { return (position - elementCenter) * (1._sreal - elementSpace) + elementCenter; } - -protected: std::array, NumberColors> renderedPoints; }; template -class DrawElementMesh{}; +struct DrawElementMesh{}; template<> -class SOFA_CORE_API DrawElementMesh +struct SOFA_CORE_API DrawElementMesh : public BaseDrawMesh, 3> { friend BaseDrawMesh; @@ -77,6 +76,7 @@ class SOFA_CORE_API DrawElementMesh sofa::type::RGBAColor::blue() }; +private: void doDraw( sofa::helper::visual::DrawTool* drawTool, const type::vector& position, @@ -85,7 +85,7 @@ class SOFA_CORE_API DrawElementMesh }; template<> -class SOFA_CORE_API DrawElementMesh +struct SOFA_CORE_API DrawElementMesh : public BaseDrawMesh, 4> { friend BaseDrawMesh; @@ -98,6 +98,7 @@ class SOFA_CORE_API DrawElementMesh sofa::type::RGBAColor::cyan() }; +private: void doDraw(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology, @@ -105,7 +106,7 @@ class SOFA_CORE_API DrawElementMesh }; template<> -class SOFA_CORE_API DrawElementMesh +struct SOFA_CORE_API DrawElementMesh : public BaseDrawMesh, 6> { friend BaseDrawMesh; @@ -120,6 +121,7 @@ class SOFA_CORE_API DrawElementMesh sofa::type::RGBAColor(0.7f,0.1f,0.7f,1.f) }; +private: void doDraw( sofa::helper::visual::DrawTool* drawTool, const type::vector& position, @@ -131,9 +133,15 @@ class SOFA_CORE_API DrawMesh { public: - void drawTriangles(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); - void drawTetrahedra(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); - void drawHexahedra(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); + template + void drawElements( + sofa::helper::visual::DrawTool* drawTool, + const type::vector& position, + sofa::core::topology::BaseMeshTopology* topology, + const DrawElementMesh::ColorContainer& colors = DrawElementMesh::defaultColors) + { + std::get>(m_meshes).draw(drawTool, position, topology, colors); + } void setElementSpace(SReal elementSpace); @@ -143,10 +151,11 @@ class SOFA_CORE_API DrawMesh void draw(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); private: - - DrawElementMesh m_drawTriangleMesh; - DrawElementMesh m_drawTetrahedronMesh; - DrawElementMesh m_drawHexahedronMesh; + std::tuple< + DrawElementMesh, + DrawElementMesh, + DrawElementMesh + > m_meshes; }; } // namespace sofa::core::visual From f541a31613a7a377ac324060d2d8c956831b3abd Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 21 Nov 2025 13:42:08 +0100 Subject: [PATCH 14/26] use DrawElementMesh in TetrahedronHyperelasticityFEMDrawing --- .../TetrahedronHyperelasticityFEMDrawing.h | 106 +++++------------- 1 file changed, 25 insertions(+), 81 deletions(-) diff --git a/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h b/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h index a411b930afa..4c04c1c5a86 100644 --- a/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h +++ b/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h @@ -20,19 +20,17 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -#include - -#include -#include - #include -#include -#include -#include -#include #include +#include +#include #include - +#include +#include +#include +#include +#include +#include namespace sofa::component::solidmechanics::fem::hyperelastic { @@ -42,56 +40,56 @@ void selectColors(const std::string& materialName, sofa::type::RGBAColor& color1 { if (materialName == material::BoyceAndArruda::Name) { - color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0); - color2 = type::RGBAColor(0.5, 1.0, 0.0, 1.0); - color3 = type::RGBAColor(1.0, 1.0, 0.0, 1.0); + color1 = type::RGBAColor::green(); + color2 = type::RGBAColor::lime(); + color3 = type::RGBAColor::yellow(); color4 = type::RGBAColor(1.0, 1.0, 0.5, 1.0); } else if (materialName == material::STVenantKirchhoff::Name) { - color1 = type::RGBAColor(1.0,0.0,0.0,1.0); - color2 = type::RGBAColor(1.0,0.0,0.5,1.0); - color3 = type::RGBAColor(1.0,1.0,0.0,1.0); + color1 = type::RGBAColor::red(); + color2 = type::RGBAColor::pink(); + color3 = type::RGBAColor::yellow(); color4 = type::RGBAColor(1.0,0.5,1.0,1.0); } else if (materialName == material::NeoHookean::Name) { - color1 = type::RGBAColor(0.0, 1.0, 1.0, 1.0); + color1 = type::RGBAColor::cyan(); color2 = type::RGBAColor(0.5, 0.0, 1.0, 1.0); - color3 = type::RGBAColor(1.0, 0.0, 1.0, 1.0); + color3 = type::RGBAColor::magenta(); color4 = type::RGBAColor(1.0, 0.5, 1.0, 1.0); } else if (materialName == material::MooneyRivlin::Name) { - color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0); + color1 = type::RGBAColor::green(); color2 = type::RGBAColor(0.0, 1.0, 0.5, 1.0); - color3 = type::RGBAColor(0.0, 1.0, 1.0, 1.0); + color3 = type::RGBAColor::cyan(); color4 = type::RGBAColor(0.5, 1.0, 1.0, 1.0); } else if (materialName == material::VerondaWestman::Name) { - color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0); + color1 = type::RGBAColor::green(); color2 = type::RGBAColor(0.5, 1.0, 0.0, 1.0); color3 = type::RGBAColor(1.0, 1.0, 0.0, 1.0); color4 = type::RGBAColor(1.0, 1.0, 0.5, 1.0); } else if (materialName == material::Costa::Name) { - color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0); + color1 = type::RGBAColor::green(); color2 = type::RGBAColor(0.5, 1.0, 0.0, 1.0); color3 = type::RGBAColor(1.0, 1.0, 0.0, 1.0); color4 = type::RGBAColor(1.0, 1.0, 0.5, 1.0); } else if (materialName == material::Ogden::Name) { - color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0); + color1 = type::RGBAColor::green(); color2 = type::RGBAColor(0.5, 1.0, 0.0, 1.0); color3 = type::RGBAColor(1.0, 1.0, 0.0, 1.0); color4 = type::RGBAColor(1.0, 1.0, 0.5, 1.0); } else { - color1 = type::RGBAColor(0.0, 1.0, 0.0, 1.0); + color1 = type::RGBAColor::green(); color2 = type::RGBAColor(0.5, 1.0, 0.0, 1.0); color3 = type::RGBAColor(1.0, 1.0, 0.0, 1.0); color4 = type::RGBAColor(1.0, 1.0, 0.5, 1.0); @@ -102,67 +100,13 @@ template void drawHyperelasticTets(const core::visual::VisualParams* vparams, const typename DataTypes::VecCoord& x, core::topology::BaseMeshTopology* topology, - const std::string& materialName, - const sofa::type::vector& indicesToDraw) + const std::string& materialName) { - std::vector points[4]; - for(auto& p : points) - { - p.reserve(3 * indicesToDraw.size()); - } - - const auto& tetrahedra = topology->getTetrahedra(); - - for(const auto i : indicesToDraw) - { - const auto t = tetrahedra[i]; - - const Index a = t[0]; - const Index b = t[1]; - const Index c = t[2]; - const Index d = t[3]; - - const auto center = (x[a] + x[b] + x[c] + x[d]) * 0.125; - const auto pa = (x[a] + center) * 0.666667; - const auto pb = (x[b] + center) * 0.666667; - const auto pc = (x[c] + center) * 0.666667; - const auto pd = (x[d] + center) * 0.666667; - - points[0].push_back(pa); - points[0].push_back(pb); - points[0].push_back(pc); - - points[1].push_back(pb); - points[1].push_back(pc); - points[1].push_back(pd); - - points[2].push_back(pc); - points[2].push_back(pd); - points[2].push_back(pa); - - points[3].push_back(pd); - points[3].push_back(pa); - points[3].push_back(pb); - } - std::array colors; selectColors(materialName, colors[0], colors[1], colors[2], colors[3]); - vparams->drawTool()->drawTriangles(points[0], colors[0]); - vparams->drawTool()->drawTriangles(points[1], colors[1]); - vparams->drawTool()->drawTriangles(points[2], colors[2]); - vparams->drawTool()->drawTriangles(points[3], colors[3]); -} - -template -void drawHyperelasticTets(const core::visual::VisualParams* vparams, - const typename DataTypes::VecCoord& x, - core::topology::BaseMeshTopology* topology, - const std::string& materialName) -{ - sofa::type::vector allIndices(topology->getNbTetrahedra()); - std::iota(allIndices.begin(), allIndices.end(), static_cast(0)); - drawHyperelasticTets(vparams, x, topology, materialName, allIndices); + core::visual::DrawElementMesh drawer; + drawer.draw(vparams->drawTool(), x, topology, colors); } From bbb7f7ae417f7679a0cf1562719ff858362c078e Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 21 Nov 2025 13:56:03 +0100 Subject: [PATCH 15/26] use DrawElementMesh in volume force fields --- .../FastTetrahedralCorotationalForceField.h | 9 +- .../FastTetrahedralCorotationalForceField.inl | 45 +------- .../fem/elastic/HexahedralFEMForceField.h | 14 +-- .../fem/elastic/HexahedralFEMForceField.inl | 90 +--------------- .../fem/elastic/HexahedronFEMForceField.h | 16 +-- .../fem/elastic/HexahedronFEMForceField.inl | 102 +----------------- .../TetrahedralCorotationalFEMForceField.h | 12 ++- .../TetrahedralCorotationalFEMForceField.inl | 48 ++------- 8 files changed, 39 insertions(+), 297 deletions(-) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.h index 770ea885bd2..b69b3e00f00 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.h @@ -25,11 +25,12 @@ #include #include #include -#include -#include -#include +#include #include +#include +#include #include +#include namespace sofa::component::solidmechanics::fem::elastic { @@ -177,6 +178,8 @@ protected : typedef FastTetrahedralCorotationalForceFieldData ExtraData; ExtraData m_data; + + core::visual::DrawElementMesh m_drawMesh; }; #if !defined(SOFA_COMPONENT_INTERACTIONFORCEFIELD_FASTTETRAHEDRALCOROTATIONALFORCEFIELD_CPP) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.inl index 434e54e7261..9037ed49b79 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.inl @@ -672,50 +672,7 @@ void FastTetrahedralCorotationalForceField::draw(const core::visual:: if (vparams->displayFlags().getShowWireFrame()) vparams->drawTool()->setPolygonMode(0, true); - - std::vector< type::Vec3 > points[4]; - for (size_t i = 0; il_topology->getNbTetrahedra(); ++i) - { - const core::topology::BaseMeshTopology::Tetrahedron t = this->l_topology->getTetrahedron(i); - - const auto& [a, b, c, d] = t.array(); - Coord center = (x[a] + x[b] + x[c] + x[d])*0.125; - Coord pa = (x[a] + center)*(Real)0.666667; - Coord pb = (x[b] + center)*(Real)0.666667; - Coord pc = (x[c] + center)*(Real)0.666667; - Coord pd = (x[d] + center)*(Real)0.666667; - - // glColor4f(0,0,1,1); - points[0].push_back(pa); - points[0].push_back(pb); - points[0].push_back(pc); - - // glColor4f(0,0.5,1,1); - points[1].push_back(pb); - points[1].push_back(pc); - points[1].push_back(pd); - - // glColor4f(0,1,1,1); - points[2].push_back(pc); - points[2].push_back(pd); - points[2].push_back(pa); - - // glColor4f(0.5,1,1,1); - points[3].push_back(pd); - points[3].push_back(pa); - points[3].push_back(pb); - } - - vparams->drawTool()->drawTriangles(points[0], d_drawColor1.getValue()); - vparams->drawTool()->drawTriangles(points[1], d_drawColor2.getValue()); - vparams->drawTool()->drawTriangles(points[2], d_drawColor3.getValue()); - vparams->drawTool()->drawTriangles(points[3], d_drawColor4.getValue()); - - if (vparams->displayFlags().getShowWireFrame()) - vparams->drawTool()->setPolygonMode(0, false); - - - + m_drawMesh.draw(vparams->drawTool(), x, this->l_topology.get()); } } // namespace sofa::component::solidmechanics::fem::elastic diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.h index 27af165194a..fc250785b94 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.h @@ -20,15 +20,13 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -#include - #include - -#include -#include -#include - +#include #include +#include +#include +#include +#include namespace sofa::component::solidmechanics::fem::elastic { @@ -198,6 +196,8 @@ class HexahedralFEMForceField : virtual public BaseLinearElasticityFEMForceField protected: type::Mat<8,3,int> _coef; ///< coef of each vertices to compute the strain stress matrix + + core::visual::DrawElementMesh drawMesh; }; #if !defined(SOFA_COMPONENT_FORCEFIELD_HEXAHEDRALFEMFORCEFIELD_CPP) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.inl index 949d5421c4f..978c9b7c74f 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.inl @@ -659,9 +659,6 @@ void HexahedralFEMForceField::draw(const core::visual::VisualParams* if (!this->mstate) return; const auto stateLifeCycle = vparams->drawTool()->makeStateLifeCycle(); - vparams->drawTool()->disableLighting(); - std::vector colorVector; - std::vector vertices; const VecCoord& x = this->mstate->read(core::vec_id::read_access::position)->getValue(); @@ -670,92 +667,7 @@ void HexahedralFEMForceField::draw(const core::visual::VisualParams* vparams->drawTool()->setPolygonMode(0, true); } - for(size_t i = 0 ; il_topology->getNbHexahedra(); ++i) - { - const core::topology::BaseMeshTopology::Hexahedron &t=this->l_topology->getHexahedron(i); - - Index a = t[0]; - Index b = t[1]; - Index d = t[2]; - Index c = t[3]; - Index e = t[4]; - Index f = t[5]; - Index h = t[6]; - Index g = t[7]; - - Coord center = (x[a]+x[b]+x[c]+x[d]+x[e]+x[g]+x[f]+x[h])*0.125; - Real percentage = (Real) 0.15; - Coord p0 = x[a]-(x[a]-center)*percentage; - Coord p1 = x[b]-(x[b]-center)*percentage; - Coord p2 = x[c]-(x[c]-center)*percentage; - Coord p3 = x[d]-(x[d]-center)*percentage; - Coord p4 = x[e]-(x[e]-center)*percentage; - Coord p5 = x[f]-(x[f]-center)*percentage; - Coord p6 = x[g]-(x[g]-center)*percentage; - Coord p7 = x[h]-(x[h]-center)*percentage; - - constexpr sofa::type::RGBAColor color1(0.7f, 0.7f, 0.1f, 1.0f); - colorVector.push_back(color1); - colorVector.push_back(color1); - colorVector.push_back(color1); - colorVector.push_back(color1); - vertices.push_back(DataTypes::getCPos(p5)); - vertices.push_back(DataTypes::getCPos(p1)); - vertices.push_back(DataTypes::getCPos(p3)); - vertices.push_back(DataTypes::getCPos(p7)); - - constexpr sofa::type::RGBAColor color2(0.7f, 0.0f, 0.0f, 1.0f); - colorVector.push_back(color2); - colorVector.push_back(color2); - colorVector.push_back(color2); - colorVector.push_back(color2); - vertices.push_back(DataTypes::getCPos(p1)); - vertices.push_back(DataTypes::getCPos(p0)); - vertices.push_back(DataTypes::getCPos(p2)); - vertices.push_back(DataTypes::getCPos(p3)); - - constexpr sofa::type::RGBAColor color3(0.0f, 0.7f, 0.0f, 1.0f); - colorVector.push_back(color3); - colorVector.push_back(color3); - colorVector.push_back(color3); - colorVector.push_back(color3); - vertices.push_back(DataTypes::getCPos(p0)); - vertices.push_back(DataTypes::getCPos(p4)); - vertices.push_back(DataTypes::getCPos(p6)); - vertices.push_back(DataTypes::getCPos(p2)); - - constexpr sofa::type::RGBAColor color4(0.0f, 0.0f, 0.7f, 1.0f); - colorVector.push_back(color4); - colorVector.push_back(color4); - colorVector.push_back(color4); - colorVector.push_back(color4); - vertices.push_back(DataTypes::getCPos(p4)); - vertices.push_back(DataTypes::getCPos(p5)); - vertices.push_back(DataTypes::getCPos(p7)); - vertices.push_back(DataTypes::getCPos(p6)); - - constexpr sofa::type::RGBAColor color5(0.1f, 0.7f, 0.7f, 1.0f); - colorVector.push_back(color5); - colorVector.push_back(color5); - colorVector.push_back(color5); - colorVector.push_back(color5); - vertices.push_back(DataTypes::getCPos(p7)); - vertices.push_back(DataTypes::getCPos(p3)); - vertices.push_back(DataTypes::getCPos(p2)); - vertices.push_back(DataTypes::getCPos(p6)); - - constexpr sofa::type::RGBAColor color6(0.1f, 0.7f, 0.7f, 1.0f); - colorVector.push_back(color6); - colorVector.push_back(color6); - colorVector.push_back(color6); - colorVector.push_back(color6); - vertices.push_back(DataTypes::getCPos(p1)); - vertices.push_back(DataTypes::getCPos(p5)); - vertices.push_back(DataTypes::getCPos(p4)); - vertices.push_back(DataTypes::getCPos(p0)); - } - vparams->drawTool()->drawQuads(vertices,colorVector); - + drawMesh.draw(vparams->drawTool(), x, this->l_topology.get()); } } // namespace sofa::component::solidmechanics::fem::elastic diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.h index 81171ce7709..9a76c7ae675 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.h @@ -20,17 +20,17 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -#include - #include -#include +#include #include -#include -#include -#include #include -#include +#include +#include +#include #include +#include +#include +#include namespace sofa::component::solidmechanics::fem::elastic { @@ -222,6 +222,8 @@ class HexahedronFEMForceField : virtual void accumulateForceSmall( WDataRefVecDeriv &f, RDataRefVecCoord &p, sofa::Index i, const Element&elem ); bool _alreadyInit; + + core::visual::DrawElementMesh drawMesh; }; #if !defined(SOFA_COMPONENT_FORCEFIELD_HEXAHEDRONFEMFORCEFIELD_CPP) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.inl index af0cb62553b..7c71cab0286 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.inl @@ -1212,8 +1212,6 @@ void HexahedronFEMForceField::draw(const core::visual::VisualParams* const VecCoord& x = this->mstate->read(core::vec_id::read_access::position)->getValue(); - vparams->drawTool()->setLightingEnabled(false); - if(_sparseGrid ) { vparams->drawTool()->enableBlending(); @@ -1222,104 +1220,8 @@ void HexahedronFEMForceField::draw(const core::visual::VisualParams* if (vparams->displayFlags().getShowWireFrame()) vparams->drawTool()->setPolygonMode(0,true); - const Real percentage = d_drawPercentageOffset.getValue(); - const Real oneMinusPercentage = static_cast(1) - percentage; - - const auto* indexedElements = this->getIndexedElements(); - - sofa::type::fixed_array, 6 > quads; //one list of quads per hexahedron face - sofa::type::fixed_array, 6> colors; //one list of quads per hexahedron face - - for (auto& q : quads) - { - q.reserve(indexedElements->size() * 4); - } - for (auto& c : colors) - { - c.reserve(indexedElements->size() * 4); - } - - sofa::Index i {}; - for (const auto& element : *indexedElements) - { - const Coord& a = x[element[0]]; - const Coord& b = x[element[1]]; - const Coord& c = x[element[2]]; - const Coord& d = x[element[3]]; - const Coord& e = x[element[4]]; - const Coord& f = x[element[5]]; - const Coord& g = x[element[6]]; - const Coord& h = x[element[7]]; - - const Coord center = (a + b + c + d + e + f + g + h ) * static_cast(0.125); - const Coord centerPercent = center * percentage; - - const Coord pa = a * oneMinusPercentage + centerPercent; - const Coord pb = b * oneMinusPercentage + centerPercent; - const Coord pc = c * oneMinusPercentage + centerPercent; - const Coord pd = d * oneMinusPercentage + centerPercent; - const Coord pe = e * oneMinusPercentage + centerPercent; - const Coord pf = f * oneMinusPercentage + centerPercent; - const Coord pg = g * oneMinusPercentage + centerPercent; - const Coord ph = h * oneMinusPercentage + centerPercent; - - quads[0].emplace_back(pa); - quads[0].emplace_back(pb); - quads[0].emplace_back(pc); - quads[0].emplace_back(pd); - - quads[1].emplace_back(pe); - quads[1].emplace_back(pf); - quads[1].emplace_back(pg); - quads[1].emplace_back(ph); - - quads[2].emplace_back(pc); - quads[2].emplace_back(pd); - quads[2].emplace_back(ph); - quads[2].emplace_back(pg); - - quads[3].emplace_back(pa); - quads[3].emplace_back(pb); - quads[3].emplace_back(pf); - quads[3].emplace_back(pe); - - quads[4].emplace_back(pa); - quads[4].emplace_back(pd); - quads[4].emplace_back(ph); - quads[4].emplace_back(pe); - - quads[5].emplace_back(pb); - quads[5].emplace_back(pc); - quads[5].emplace_back(pg); - quads[5].emplace_back(pf); - - const float stiffnessCoef = _sparseGrid ? _sparseGrid->getStiffnessCoef(i) : 1.0f; - sofa::type::fixed_array quadColors { - sofa::type::RGBAColor(0.7f,0.7f,0.1f,stiffnessCoef), - sofa::type::RGBAColor(0.7f,0.0f,0.0f,stiffnessCoef), - sofa::type::RGBAColor(0.0f,0.7f,0.0f,stiffnessCoef), - sofa::type::RGBAColor(0.0f,0.0f,0.7f,stiffnessCoef), - sofa::type::RGBAColor(0.1f,0.7f,0.7f,stiffnessCoef), - sofa::type::RGBAColor(0.7f,0.1f,0.7f,stiffnessCoef) - }; - - for (unsigned int j = 0; j < 6; ++j) - { - auto& faceColors = colors[j]; - const auto& color = quadColors[j]; - for (unsigned int k = 0; k < 4; ++k) - { - faceColors.emplace_back(color); - } - } - - ++i; - } - - for (unsigned int j = 0; j < 6; ++j) - { - vparams->drawTool()->drawQuads(quads[j], colors[j]); - } + drawMesh.elementSpace = d_drawPercentageOffset.getValue(); + drawMesh.draw(vparams->drawTool(), x, this->l_topology.get()); } diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.h index bb48014af31..d5116e2f8ea 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.h @@ -22,14 +22,14 @@ #pragma once #include #include - #include #include -#include -#include -#include -#include +#include #include +#include +#include +#include +#include // corotational tetrahedron from // @InProceedings{NPF05, @@ -250,6 +250,8 @@ class TetrahedralCorotationalFEMForceField : public BaseLinearElasticityFEMForce void printStiffnessMatrix(int idTetra); + core::visual::DrawElementMesh m_drawMesh; + }; #if !defined(SOFA_COMPONENT_FORCEFIELD_TETRAHEDRALCOROTATIONALFEMFORCEFIELD_CPP) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.inl index a574c00230a..e3ad594d694 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.inl @@ -1353,49 +1353,13 @@ void TetrahedralCorotationalFEMForceField::draw(const core::visual::V if (d_drawing.getValue()) { - const sofa::Size nbrTetra = this->l_topology->getNbTetrahedra(); - std::vector< type::Vec3 > points[4]; - points[0].reserve(nbrTetra * 3); - points[1].reserve(nbrTetra * 3); - points[2].reserve(nbrTetra * 3); - points[3].reserve(nbrTetra * 3); - - for(Size i = 0 ; i< nbrTetra; ++i) - { - const core::topology::BaseMeshTopology::Tetrahedron t=this->l_topology->getTetrahedron(i); - - const auto& [a, b, c, d] = t.array(); - Coord center = (x[a] + x[b] + x[c] + x[d]) * 0.125; - Coord pa = (x[a] + center) * (Real)0.666667; - Coord pb = (x[b] + center) * (Real)0.666667; - Coord pc = (x[c] + center) * (Real)0.666667; - Coord pd = (x[d] + center) * (Real)0.666667; - - points[0].push_back(pa); - points[0].push_back(pb); - points[0].push_back(pc); - - points[1].push_back(pb); - points[1].push_back(pc); - points[1].push_back(pd); - - points[2].push_back(pc); - points[2].push_back(pd); - points[2].push_back(pa); - - points[3].push_back(pd); - points[3].push_back(pa); - points[3].push_back(pb); - } - - vparams->drawTool()->drawTriangles(points[0], d_drawColor1.getValue()); - vparams->drawTool()->drawTriangles(points[1], d_drawColor2.getValue()); - vparams->drawTool()->drawTriangles(points[2], d_drawColor3.getValue()); - vparams->drawTool()->drawTriangles(points[3], d_drawColor4.getValue()); + std::array colors { + d_drawColor1.getValue(), + d_drawColor2.getValue(), + d_drawColor3.getValue(), + d_drawColor4.getValue()}; + m_drawMesh.draw(vparams->drawTool(), x, this->l_topology.get(), colors); } - - if (vparams->displayFlags().getShowWireFrame()) - vparams->drawTool()->setPolygonMode(0,false); } From 48daffb4f6e6180c22dff929eb15f1b04b8e0581 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 21 Nov 2025 14:00:12 +0100 Subject: [PATCH 16/26] use DrawElementMesh in surface force fields --- .../fem/elastic/TriangleFEMForceField.h | 10 ++++++---- .../fem/elastic/TriangleFEMForceField.inl | 20 +------------------ 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.h index b17f79a837b..b7a64ba2234 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.h @@ -21,12 +21,12 @@ ******************************************************************************/ #pragma once -#include -#include #include - -#include +#include +#include +#include #include +#include // corotational triangle from // @InProceedings{NPF05, @@ -156,6 +156,8 @@ class TriangleFEMForceField : public BaseLinearElasticityFEMForceField m_triangleUtils; + + core::visual::DrawElementMesh m_drawMesh; }; diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.inl index 3348ff01e90..efd462e4b48 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.inl @@ -546,31 +546,13 @@ void TriangleFEMForceField::draw(const core::visual::VisualParams* vp return; const auto stateLifeCycle = vparams->drawTool()->makeStateLifeCycle(); - vparams->drawTool()->disableLighting(); if (vparams->displayFlags().getShowWireFrame()) vparams->drawTool()->setPolygonMode(0, true); - std::vector colorVector; - std::vector vertices; - const VecCoord& x = this->mstate->read(core::vec_id::read_access::position)->getValue(); - typename VecElement::const_iterator it; - for (it = _indexedElements->begin(); it != _indexedElements->end(); ++it) - { - const auto& [a, b, c] = it->array(); - - colorVector.push_back(sofa::type::RGBAColor::green()); - vertices.push_back(sofa::type::Vec3(x[a])); - colorVector.push_back(sofa::type::RGBAColor(0, 0.5, 0.5, 1)); - vertices.push_back(sofa::type::Vec3(x[b])); - colorVector.push_back(sofa::type::RGBAColor(0, 0, 1, 1)); - vertices.push_back(sofa::type::Vec3(x[c])); - } - vparams->drawTool()->drawTriangles(vertices, colorVector); - - + m_drawMesh.draw(vparams->drawTool(), x, this->l_topology.get()); } From 91db5dcc4b9d9af50b24a537e80828aeb472f305 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Wed, 10 Dec 2025 16:19:05 +0100 Subject: [PATCH 17/26] missing typename --- Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index 67cbf95df0d..49d158d6a05 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -138,7 +138,7 @@ class SOFA_CORE_API DrawMesh sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology, - const DrawElementMesh::ColorContainer& colors = DrawElementMesh::defaultColors) + const typename DrawElementMesh::ColorContainer& colors = DrawElementMesh::defaultColors) { std::get>(m_meshes).draw(drawTool, position, topology, colors); } From 413df76117e20ab7320af6b0d1998606a4b275e1 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 11 Dec 2025 10:49:27 +0100 Subject: [PATCH 18/26] TEMPLATE EVERYWHERE!!! --- .../Core/src/sofa/core/visual/DrawMesh.cpp | 174 ----------------- .../Core/src/sofa/core/visual/DrawMesh.h | 179 ++++++++++++++++-- 2 files changed, 166 insertions(+), 187 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp index 1435581c05f..d077ad4a027 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.cpp @@ -24,183 +24,9 @@ namespace sofa::core::visual { -namespace -{ - -template -sofa::type::Vec3 elementCenter(const type::vector& position, const ElementType& element) -{ - sofa::type::Vec3 center{}; - for (sofa::Size vId = 0; vId < element.size(); ++vId) - { - center += position[element[vId]]; - } - center /= element.size(); - return center; -} - -} // namespace - void DrawMesh::setElementSpace(SReal elementSpace) { std::apply([elementSpace](auto&&... mesh){ ((mesh.elementSpace = elementSpace), ...); }, m_meshes); } -void DrawMesh::drawSurface(sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) -{ - drawElements(drawTool, position, topology); -} - -void DrawMesh::drawVolume(sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) -{ - drawElements(drawTool, position, topology); - drawElements(drawTool, position, topology); -} - -void DrawMesh::draw(sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology) -{ - if (!topology) - { - return; - } - - const auto hasTetra = topology && !topology->getTetrahedra().empty(); - const auto hasHexa = topology && !topology->getHexahedra().empty(); - - if (!hasTetra && !hasHexa) - { - drawSurface(drawTool, position, topology); - } - drawVolume(drawTool, position, topology); -} - -void DrawElementMesh::doDraw( - sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology, - const ColorContainer& colors) -{ - if (!topology) - return; - - const auto& elements = topology->getTriangles(); - - const auto size = (elements.size() / NumberColors + 1) * sofa::geometry::Triangle::NumberOfNodes; - for ( auto& p : renderedPoints) - { - p.resize(size); - } - - std::array renderedPointId {}; - for (sofa::Size i = 0; i < elements.size(); ++i) - { - const auto& element = elements[i]; - - const sofa::type::Vec3 center = elementCenter(position, element); - - for (std::size_t j = 0; j < sofa::geometry::Triangle::NumberOfNodes; ++j) - { - renderedPoints[i % NumberColors][renderedPointId[i%NumberColors]++] = applyElementSpace(position[element[j]], center); - } - } - - for (std::size_t j = 0; j < NumberColors; ++j) - { - drawTool->drawTriangles(renderedPoints[j], colors[j]); - } -} - -void DrawElementMesh::doDraw( - sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology, - const ColorContainer& colors) -{ - if (!topology) - return; - - const auto& elements = topology->getTetrahedra(); - const auto& facets = topology->getTriangles(); - - for ( auto& p : renderedPoints) - { - p.resize(elements.size() * sofa::geometry::Triangle::NumberOfNodes); - } - - std::size_t renderedPointId {}; - for (sofa::Size i = 0; i < elements.size(); ++i) - { - const auto& element = elements[i]; - const auto& facetsInElement = topology->getTrianglesInTetrahedron(i); - assert(facetsInElement.size() == NumberTrianglesInTetrahedron); - - const sofa::type::Vec3 center = elementCenter(position, element); - - for (std::size_t j = 0; j < NumberTrianglesInTetrahedron; ++j) - { - const auto faceId = facetsInElement[j]; - std::size_t k {}; - for (const auto vertexId : facets[faceId]) - { - renderedPoints[j][i * sofa::geometry::Triangle::NumberOfNodes + k] = applyElementSpace(position[vertexId], center); - ++k; - } - } - } - - for (std::size_t j = 0; j < NumberTrianglesInTetrahedron; ++j) - { - drawTool->drawTriangles(renderedPoints[j], colors[j]); - } -} - -void DrawElementMesh::doDraw(sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, - sofa::core::topology::BaseMeshTopology* topology, - const ColorContainer& colors) -{ - if (!topology) - return; - - const auto& elements = topology->getHexahedra(); - const auto& facets = topology->getQuads(); - - for ( auto& p : renderedPoints) - { - p.resize(elements.size() * sofa::geometry::Quad::NumberOfNodes); - } - - std::size_t renderedPointId {}; - for (sofa::Size i = 0; i < elements.size(); ++i) - { - const auto& element = elements[i]; - const auto& facetsInElement = topology->getQuadsInHexahedron(i); - assert(facetsInElement.size() == NumberTrianglesInTetrahedron); - - const sofa::type::Vec3 center = elementCenter(position, element); - - for (std::size_t j = 0; j < NumberQuadsInHexahedron; ++j) - { - const auto faceId = facetsInElement[j]; - std::size_t k {}; - for (const auto vertexId : facets[faceId]) - { - renderedPoints[j][i * sofa::geometry::Quad::NumberOfNodes + k] = applyElementSpace(position[vertexId], center); - ++k; - } - } - } - - for (std::size_t j = 0; j < NumberQuadsInHexahedron; ++j) - { - drawTool->drawQuads(renderedPoints[j], colors[j]); - } -} - } // namespace sofa::core::visual diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index 49d158d6a05..1082410a6d5 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -37,9 +37,10 @@ struct BaseDrawMesh SReal elementSpace { 0.125_sreal }; + template void draw( sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, + const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology, const ColorContainer& colors = Derived::defaultColors) { @@ -55,10 +56,24 @@ struct BaseDrawMesh } protected: - sofa::type::Vec3 applyElementSpace(const sofa::type::Vec3& position, const sofa::type::Vec3& elementCenter) const + template + PositionType applyElementSpace(const PositionType& position, const PositionType& elementCenter) const { return (position - elementCenter) * (1._sreal - elementSpace) + elementCenter; } + + template + static PositionContainer::value_type elementCenter(const PositionContainer& position, const ElementType& element) + { + typename PositionContainer::value_type center{}; + for (sofa::Size vId = 0; vId < element.size(); ++vId) + { + center += position[element[vId]]; + } + center /= element.size(); + return center; + } + std::array, NumberColors> renderedPoints; }; @@ -77,11 +92,43 @@ struct SOFA_CORE_API DrawElementMesh }; private: + template void doDraw( sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, + const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology, - const ColorContainer& colors); + const ColorContainer& colors) + { + if (!topology) + return; + + const auto& elements = topology->getTriangles(); + + const auto size = (elements.size() / NumberColors + 1) * sofa::geometry::Triangle::NumberOfNodes; + for ( auto& p : renderedPoints) + { + p.resize(size); + } + + std::array renderedPointId {}; + for (sofa::Size i = 0; i < elements.size(); ++i) + { + const auto& element = elements[i]; + + const auto center = this->elementCenter(position, element); + + for (std::size_t j = 0; j < sofa::geometry::Triangle::NumberOfNodes; ++j) + { + const auto p = this->applyElementSpace(position[element[j]], center); + renderedPoints[i % NumberColors][renderedPointId[i%NumberColors]++] = sofa::type::toVec3(p); + } + } + + for (std::size_t j = 0; j < NumberColors; ++j) + { + drawTool->drawTriangles(renderedPoints[j], colors[j]); + } + } }; template<> @@ -99,10 +146,50 @@ struct SOFA_CORE_API DrawElementMesh }; private: + template void doDraw(sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, + const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology, - const ColorContainer& colors); + const ColorContainer& colors) + { + if (!topology) + return; + + const auto& elements = topology->getTetrahedra(); + const auto& facets = topology->getTriangles(); + + for ( auto& p : renderedPoints) + { + p.resize(elements.size() * sofa::geometry::Triangle::NumberOfNodes); + } + + std::size_t renderedPointId {}; + for (sofa::Size i = 0; i < elements.size(); ++i) + { + const auto& element = elements[i]; + const auto& facetsInElement = topology->getTrianglesInTetrahedron(i); + assert(facetsInElement.size() == NumberTrianglesInTetrahedron); + + const auto center = this->elementCenter(position, element); + + for (std::size_t j = 0; j < NumberTrianglesInTetrahedron; ++j) + { + const auto faceId = facetsInElement[j]; + std::size_t k {}; + for (const auto vertexId : facets[faceId]) + { + const auto p = this->applyElementSpace(position[vertexId], center); + renderedPoints[j][i * sofa::geometry::Triangle::NumberOfNodes + k] = sofa::type::toVec3(p); + ++k; + } + } + } + + for (std::size_t j = 0; j < NumberTrianglesInTetrahedron; ++j) + { + drawTool->drawTriangles(renderedPoints[j], colors[j]); + } + } }; template<> @@ -122,21 +209,61 @@ struct SOFA_CORE_API DrawElementMesh }; private: + template void doDraw( sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, + const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology, - const ColorContainer& colors); + const ColorContainer& colors) + { + if (!topology) + return; + + const auto& elements = topology->getHexahedra(); + const auto& facets = topology->getQuads(); + + for ( auto& p : renderedPoints) + { + p.resize(elements.size() * sofa::geometry::Quad::NumberOfNodes); + } + + std::size_t renderedPointId {}; + for (sofa::Size i = 0; i < elements.size(); ++i) + { + const auto& element = elements[i]; + const auto& facetsInElement = topology->getQuadsInHexahedron(i); + assert(facetsInElement.size() == NumberTrianglesInTetrahedron); + + const auto center = this->elementCenter(position, element); + + for (std::size_t j = 0; j < NumberQuadsInHexahedron; ++j) + { + const auto faceId = facetsInElement[j]; + std::size_t k {}; + for (const auto vertexId : facets[faceId]) + { + const auto p = this->applyElementSpace(position[vertexId], center); + renderedPoints[j][i * sofa::geometry::Quad::NumberOfNodes + k] = sofa::type::toVec3(p); + ++k; + } + } + } + + for (std::size_t j = 0; j < NumberQuadsInHexahedron; ++j) + { + drawTool->drawQuads(renderedPoints[j], colors[j]); + } + } }; class SOFA_CORE_API DrawMesh { public: - template + template void drawElements( sofa::helper::visual::DrawTool* drawTool, - const type::vector& position, + const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology, const typename DrawElementMesh::ColorContainer& colors = DrawElementMesh::defaultColors) { @@ -145,10 +272,36 @@ class SOFA_CORE_API DrawMesh void setElementSpace(SReal elementSpace); - void drawSurface(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); - void drawVolume(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); + template + void drawSurface(sofa::helper::visual::DrawTool* drawTool, const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology) + { + drawElements(drawTool, position, topology); + } + + template + void drawVolume(sofa::helper::visual::DrawTool* drawTool, const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology) + { + drawElements(drawTool, position, topology); + drawElements(drawTool, position, topology); + } - void draw(sofa::helper::visual::DrawTool* drawTool, const type::vector& position, sofa::core::topology::BaseMeshTopology* topology); + template + void draw(sofa::helper::visual::DrawTool* drawTool, const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology) + { + if (!topology) + { + return; + } + + const auto hasTetra = topology && !topology->getTetrahedra().empty(); + const auto hasHexa = topology && !topology->getHexahedra().empty(); + + if (!hasTetra && !hasHexa) + { + drawSurface(drawTool, position, topology); + } + drawVolume(drawTool, position, topology); + } private: std::tuple< From bd851e5c9752f4684a5e4430fbdbfba7faea0674 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 11 Dec 2025 11:57:22 +0100 Subject: [PATCH 19/26] missing typename keyword --- Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index 1082410a6d5..88e63e9cb8a 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -63,7 +63,7 @@ struct BaseDrawMesh } template - static PositionContainer::value_type elementCenter(const PositionContainer& position, const ElementType& element) + static typename PositionContainer::value_type elementCenter(const PositionContainer& position, const ElementType& element) { typename PositionContainer::value_type center{}; for (sofa::Size vId = 0; vId < element.size(); ++vId) From 37084475d94983b0a583c86bb279f48cbcdff22d Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 11 Dec 2025 13:55:07 +0100 Subject: [PATCH 20/26] support drawing of some elements given the indices --- .../TetrahedronHyperelasticityFEMDrawing.h | 17 +++++-- .../sofa/core/topology/BaseMeshTopology.cpp | 42 +++++++++++++++++ .../src/sofa/core/topology/BaseMeshTopology.h | 3 ++ .../Core/src/sofa/core/visual/DrawMesh.h | 45 ++++++++++++++----- 4 files changed, 92 insertions(+), 15 deletions(-) diff --git a/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h b/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h index 4c04c1c5a86..b2e75d143b9 100644 --- a/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h +++ b/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h @@ -96,17 +96,28 @@ void selectColors(const std::string& materialName, sofa::type::RGBAColor& color1 } } -template +template void drawHyperelasticTets(const core::visual::VisualParams* vparams, const typename DataTypes::VecCoord& x, core::topology::BaseMeshTopology* topology, - const std::string& materialName) + const std::string& materialName, + const IndicesContainer& indices) { std::array colors; selectColors(materialName, colors[0], colors[1], colors[2], colors[3]); core::visual::DrawElementMesh drawer; - drawer.draw(vparams->drawTool(), x, topology, colors); + drawer.drawSomeElements(vparams->drawTool(), x, topology, indices, colors); +} + +template +void drawHyperelasticTets(const core::visual::VisualParams* vparams, + const typename DataTypes::VecCoord& x, + core::topology::BaseMeshTopology* topology, + const std::string& materialName) +{ + const auto indices = std::ranges::iota_view(static_cast(0), topology->getNbTetrahedra()); + drawHyperelasticTets(vparams, x, topology, materialName, indices); } diff --git a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.cpp b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.cpp index 7eb1494c17d..bbca664a8ee 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.cpp +++ b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.cpp @@ -36,6 +36,48 @@ BaseMeshTopology::BaseMeshTopology() addAlias(&fileTopology,"fileTopology"); } +template <> +Size BaseMeshTopology::getNbElements() +{ + return getNbEdges(); +} + +template <> +Size BaseMeshTopology::getNbElements() +{ + return getNbTriangles(); +} + +template <> +Size BaseMeshTopology::getNbElements() +{ + return getNbQuads(); +} + +template <> +Size BaseMeshTopology::getNbElements() +{ + return getNbTetrahedra(); +} + +template <> +Size BaseMeshTopology::getNbElements() +{ + return getNbHexahedra(); +} + +template <> +Size BaseMeshTopology::getNbElements() +{ + return getNbPrisms(); +} + +template <> +Size BaseMeshTopology::getNbElements() +{ + return getNbPyramids(); +} + /// Returns the set of edges adjacent to a given vertex. const BaseMeshTopology::EdgesAroundVertex& BaseMeshTopology::getEdgesAroundVertex(PointID) { diff --git a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h index 98d314bbe98..24078073e09 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h +++ b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h @@ -121,6 +121,9 @@ class SOFA_CORE_API BaseMeshTopology : public core::topology::Topology virtual Size getNbPrisms() { return Size(getPrisms().size()); } virtual Size getNbPyramids() { return Size(getPyramids().size()); } + template + Size getNbElements(); + virtual const Edge getEdge(EdgeID i) { return getEdges()[i]; } virtual const Triangle getTriangle(TriangleID i) { return getTriangles()[i]; } virtual const Quad getQuad(QuadID i) { return getQuads()[i]; } diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index 88e63e9cb8a..de3111a859c 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -26,6 +26,8 @@ #include #include +#include + namespace sofa::core::visual { @@ -38,11 +40,24 @@ struct BaseDrawMesh SReal elementSpace { 0.125_sreal }; template - void draw( + void drawAllElements( sofa::helper::visual::DrawTool* drawTool, const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology, const ColorContainer& colors = Derived::defaultColors) + { + const auto totalNbElements = topology->getNbElements(); + const auto elementsToDraw = std::ranges::iota_view(0, totalNbElements); + drawSomeElements(drawTool, position, topology, elementsToDraw, colors); + } + + template + void drawSomeElements( + sofa::helper::visual::DrawTool* drawTool, + const PositionContainer& position, + sofa::core::topology::BaseMeshTopology* topology, + const IndicesContainer& elementIndices, + const ColorContainer& colors = Derived::defaultColors) { if (!drawTool) return; @@ -52,7 +67,7 @@ struct BaseDrawMesh const auto stateLifeCycle = drawTool->makeStateLifeCycle(); drawTool->disableLighting(); - static_cast(*this).doDraw(drawTool, position, topology, colors); + static_cast(*this).doDraw(drawTool, position, topology, elementIndices, colors); } protected: @@ -84,6 +99,7 @@ template<> struct SOFA_CORE_API DrawElementMesh : public BaseDrawMesh, 3> { + using ElementType = sofa::geometry::Triangle; friend BaseDrawMesh; static constexpr ColorContainer defaultColors { sofa::type::RGBAColor::green(), @@ -92,11 +108,12 @@ struct SOFA_CORE_API DrawElementMesh }; private: - template + template void doDraw( sofa::helper::visual::DrawTool* drawTool, const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology, + const IndicesContainer& elementIndices, const ColorContainer& colors) { if (!topology) @@ -104,14 +121,14 @@ struct SOFA_CORE_API DrawElementMesh const auto& elements = topology->getTriangles(); - const auto size = (elements.size() / NumberColors + 1) * sofa::geometry::Triangle::NumberOfNodes; + const auto size = (elementIndices.size() / NumberColors + 1) * sofa::geometry::Triangle::NumberOfNodes; for ( auto& p : renderedPoints) { p.resize(size); } std::array renderedPointId {}; - for (sofa::Size i = 0; i < elements.size(); ++i) + for (auto i : elementIndices) { const auto& element = elements[i]; @@ -135,6 +152,7 @@ template<> struct SOFA_CORE_API DrawElementMesh : public BaseDrawMesh, 4> { + using ElementType = sofa::geometry::Tetrahedron; friend BaseDrawMesh; static constexpr std::size_t NumberTrianglesInTetrahedron = 4; @@ -146,10 +164,11 @@ struct SOFA_CORE_API DrawElementMesh }; private: - template + template void doDraw(sofa::helper::visual::DrawTool* drawTool, const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology, + const IndicesContainer& elementIndices, const ColorContainer& colors) { if (!topology) @@ -160,11 +179,11 @@ struct SOFA_CORE_API DrawElementMesh for ( auto& p : renderedPoints) { - p.resize(elements.size() * sofa::geometry::Triangle::NumberOfNodes); + p.resize(elementIndices.size() * sofa::geometry::Triangle::NumberOfNodes); } std::size_t renderedPointId {}; - for (sofa::Size i = 0; i < elements.size(); ++i) + for (auto i : elementIndices) { const auto& element = elements[i]; const auto& facetsInElement = topology->getTrianglesInTetrahedron(i); @@ -196,6 +215,7 @@ template<> struct SOFA_CORE_API DrawElementMesh : public BaseDrawMesh, 6> { + using ElementType = sofa::geometry::Hexahedron; friend BaseDrawMesh; static constexpr std::size_t NumberQuadsInHexahedron = 6; @@ -209,11 +229,12 @@ struct SOFA_CORE_API DrawElementMesh }; private: - template + template void doDraw( sofa::helper::visual::DrawTool* drawTool, const PositionContainer& position, sofa::core::topology::BaseMeshTopology* topology, + const IndicesContainer& elementIndices, const ColorContainer& colors) { if (!topology) @@ -224,11 +245,11 @@ struct SOFA_CORE_API DrawElementMesh for ( auto& p : renderedPoints) { - p.resize(elements.size() * sofa::geometry::Quad::NumberOfNodes); + p.resize(elementIndices.size() * sofa::geometry::Quad::NumberOfNodes); } std::size_t renderedPointId {}; - for (sofa::Size i = 0; i < elements.size(); ++i) + for (auto i : elementIndices) { const auto& element = elements[i]; const auto& facetsInElement = topology->getQuadsInHexahedron(i); @@ -267,7 +288,7 @@ class SOFA_CORE_API DrawMesh sofa::core::topology::BaseMeshTopology* topology, const typename DrawElementMesh::ColorContainer& colors = DrawElementMesh::defaultColors) { - std::get>(m_meshes).draw(drawTool, position, topology, colors); + std::get>(m_meshes).drawAllElements(drawTool, position, topology, colors); } void setElementSpace(SReal elementSpace); From ceff6fb4242a86a135ded8266a904bc0a9f5f1e8 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 11 Dec 2025 14:16:34 +0100 Subject: [PATCH 21/26] add documentation --- .../src/sofa/core/topology/BaseMeshTopology.h | 12 +++++ .../Core/src/sofa/core/visual/DrawMesh.h | 45 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h index 24078073e09..0393c16f234 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h +++ b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h @@ -121,6 +121,18 @@ class SOFA_CORE_API BaseMeshTopology : public core::topology::Topology virtual Size getNbPrisms() { return Size(getPrisms().size()); } virtual Size getNbPyramids() { return Size(getPyramids().size()); } + /** + * @brief Returns the number of elements of a specific type + * @tparam ElementType The type of element (e.g., sofa::geometry::Triangle, + * sofa::geometry::Tetrahedron) + * + * Example: + * @code + * sofa::core::topology::BaseMeshTopology* topology = ...; + * Size nbTriangles = topology->getNbElements(); + * Size nbTetrahedra = topology->getNbElements(); + * @endcode + */ template Size getNbElements(); diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index de3111a859c..31ea1d4cdfc 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -31,6 +31,10 @@ namespace sofa::core::visual { +/** + * @class BaseDrawMesh + * @brief Base class for mesh drawing using Curiously Recurring Template Pattern (CRTP) + */ template struct BaseDrawMesh { @@ -39,6 +43,21 @@ struct BaseDrawMesh SReal elementSpace { 0.125_sreal }; + /** + * @brief Draws all elements of the mesh using provided colors. + * + * This function draws all elements of the mesh (from index 0 to the total number of elements) + * using the specified colors. It serves as a convenience wrapper that calls \ref + * drawSomeElements with all element indices. + * + * @tparam PositionContainer The type of the position container (e.g., + * sofa::type::vector) + * @param drawTool The drawing tool to use for rendering + * @param position The container of vertex positions + * @param topology The mesh topology + * @param colors The colors to use for each element. If not specified, the default colors of the + * derived class are used. + */ template void drawAllElements( sofa::helper::visual::DrawTool* drawTool, @@ -51,6 +70,23 @@ struct BaseDrawMesh drawSomeElements(drawTool, position, topology, elementsToDraw, colors); } + /** + * @brief Draws a subset of elements of the mesh using provided colors. + * + * This function draws a specific subset of elements (specified by element indices) using the + * provided colors. + * + * @tparam PositionContainer The type of the position container (e.g., + * sofa::type::vector) + * @tparam IndicesContainer The type of container holding element indices (e.g., + * sofa::type::vector) + * @param drawTool The drawing tool to use for rendering + * @param position The container of vertex positions + * @param topology The mesh topology + * @param elementIndices The indices of elements to draw + * @param colors The colors to use for each element. If not specified, the default colors of the + * derived class are used. + */ template void drawSomeElements( sofa::helper::visual::DrawTool* drawTool, @@ -89,6 +125,15 @@ struct BaseDrawMesh return center; } + /** + * @brief Pre-allocated point buffers for rendering different color channels + * + * This static array holds pre-allocated vertex position buffers for each color channel. + * + * Key characteristics: + * - Each buffer corresponds to one of the `NumberColors` color channels (e.g., 3 for triangles) + * - Designed for efficient reuse across multiple drawing calls without reallocation + */ std::array, NumberColors> renderedPoints; }; From d468b84e600b2fb0124d3bfc21a6373cc440b937 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 11 Dec 2025 17:30:16 +0100 Subject: [PATCH 22/26] fix template deduction --- Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index 31ea1d4cdfc..a4c9d88df07 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -66,7 +66,7 @@ struct BaseDrawMesh const ColorContainer& colors = Derived::defaultColors) { const auto totalNbElements = topology->getNbElements(); - const auto elementsToDraw = std::ranges::iota_view(0, totalNbElements); + const auto elementsToDraw = std::ranges::iota_view(static_cast(0), totalNbElements); drawSomeElements(drawTool, position, topology, elementsToDraw, colors); } From cf6d5ef45c7f1250b56e3e00a21416f2314e6102 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Thu, 11 Dec 2025 22:16:54 +0100 Subject: [PATCH 23/26] apply renaming --- .../fem/elastic/FastTetrahedralCorotationalForceField.inl | 2 +- .../solidmechanics/fem/elastic/HexahedralFEMForceField.h | 2 +- .../solidmechanics/fem/elastic/HexahedralFEMForceField.inl | 2 +- .../solidmechanics/fem/elastic/HexahedronFEMForceField.h | 2 +- .../solidmechanics/fem/elastic/HexahedronFEMForceField.inl | 4 ++-- .../fem/elastic/TetrahedralCorotationalFEMForceField.inl | 2 +- .../solidmechanics/fem/elastic/TriangleFEMForceField.inl | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.inl index 9037ed49b79..f498d5d9ecc 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/FastTetrahedralCorotationalForceField.inl @@ -672,7 +672,7 @@ void FastTetrahedralCorotationalForceField::draw(const core::visual:: if (vparams->displayFlags().getShowWireFrame()) vparams->drawTool()->setPolygonMode(0, true); - m_drawMesh.draw(vparams->drawTool(), x, this->l_topology.get()); + m_drawMesh.drawAllElements(vparams->drawTool(), x, this->l_topology.get()); } } // namespace sofa::component::solidmechanics::fem::elastic diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.h index fc250785b94..88902931200 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.h @@ -197,7 +197,7 @@ class HexahedralFEMForceField : virtual public BaseLinearElasticityFEMForceField type::Mat<8,3,int> _coef; ///< coef of each vertices to compute the strain stress matrix - core::visual::DrawElementMesh drawMesh; + core::visual::DrawElementMesh m_drawMesh; }; #if !defined(SOFA_COMPONENT_FORCEFIELD_HEXAHEDRALFEMFORCEFIELD_CPP) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.inl index 978c9b7c74f..cfe1019acd8 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedralFEMForceField.inl @@ -667,7 +667,7 @@ void HexahedralFEMForceField::draw(const core::visual::VisualParams* vparams->drawTool()->setPolygonMode(0, true); } - drawMesh.draw(vparams->drawTool(), x, this->l_topology.get()); + m_drawMesh.drawAllElements(vparams->drawTool(), x, this->l_topology.get()); } } // namespace sofa::component::solidmechanics::fem::elastic diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.h b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.h index 9a76c7ae675..bf5cd2251dc 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.h +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.h @@ -223,7 +223,7 @@ class HexahedronFEMForceField : bool _alreadyInit; - core::visual::DrawElementMesh drawMesh; + core::visual::DrawElementMesh m_drawMesh; }; #if !defined(SOFA_COMPONENT_FORCEFIELD_HEXAHEDRONFEMFORCEFIELD_CPP) diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.inl index 7c71cab0286..6d94c939400 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/HexahedronFEMForceField.inl @@ -1220,8 +1220,8 @@ void HexahedronFEMForceField::draw(const core::visual::VisualParams* if (vparams->displayFlags().getShowWireFrame()) vparams->drawTool()->setPolygonMode(0,true); - drawMesh.elementSpace = d_drawPercentageOffset.getValue(); - drawMesh.draw(vparams->drawTool(), x, this->l_topology.get()); + m_drawMesh.elementSpace = d_drawPercentageOffset.getValue(); + m_drawMesh.drawAllElements(vparams->drawTool(), x, this->l_topology.get()); } diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.inl index e3ad594d694..680b6709850 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TetrahedralCorotationalFEMForceField.inl @@ -1358,7 +1358,7 @@ void TetrahedralCorotationalFEMForceField::draw(const core::visual::V d_drawColor2.getValue(), d_drawColor3.getValue(), d_drawColor4.getValue()}; - m_drawMesh.draw(vparams->drawTool(), x, this->l_topology.get(), colors); + m_drawMesh.drawAllElements(vparams->drawTool(), x, this->l_topology.get(), colors); } } diff --git a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.inl b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.inl index efd462e4b48..6ddcda0fb9f 100644 --- a/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.inl +++ b/Sofa/Component/SolidMechanics/FEM/Elastic/src/sofa/component/solidmechanics/fem/elastic/TriangleFEMForceField.inl @@ -552,7 +552,7 @@ void TriangleFEMForceField::draw(const core::visual::VisualParams* vp const VecCoord& x = this->mstate->read(core::vec_id::read_access::position)->getValue(); - m_drawMesh.draw(vparams->drawTool(), x, this->l_topology.get()); + m_drawMesh.drawAllElements(vparams->drawTool(), x, this->l_topology.get()); } From 41d53e12c5895d0d80bb081e80ec5a6ba44430ec Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 12 Dec 2025 10:08:35 +0100 Subject: [PATCH 24/26] unused variable --- Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index a4c9d88df07..a8896838c08 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -227,7 +227,6 @@ struct SOFA_CORE_API DrawElementMesh p.resize(elementIndices.size() * sofa::geometry::Triangle::NumberOfNodes); } - std::size_t renderedPointId {}; for (auto i : elementIndices) { const auto& element = elements[i]; From c8a6fcff73d19ee3b37ebc56efba60742fea8890 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 12 Dec 2025 11:01:20 +0100 Subject: [PATCH 25/26] fix link issues --- .../Core/src/sofa/core/topology/BaseMeshTopology.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h index 0393c16f234..78bedc85b30 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h +++ b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h @@ -339,4 +339,15 @@ class SOFA_CORE_API BaseMeshTopology : public core::topology::Topology bool removeInNode( objectmodel::BaseNode* node ) override; }; + +template<> SOFA_CORE_API Size BaseMeshTopology::getNbElements(); +template<> SOFA_CORE_API Size BaseMeshTopology::getNbElements(); +template<> SOFA_CORE_API Size BaseMeshTopology::getNbElements(); +template<> SOFA_CORE_API Size BaseMeshTopology::getNbElements(); +template<> SOFA_CORE_API Size BaseMeshTopology::getNbElements(); +template<> SOFA_CORE_API Size BaseMeshTopology::getNbElements(); +template<> SOFA_CORE_API Size BaseMeshTopology::getNbElements(); + + + } // namespace sofa::core::topology From 1e38be28d96ba3b7a46bc3145ddd1b925a793396 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Fri, 12 Dec 2025 11:02:54 +0100 Subject: [PATCH 26/26] replace std::ranges::iota_view by a custom equivalent --- .../TetrahedronHyperelasticityFEMDrawing.h | 2 +- .../Core/src/sofa/core/visual/DrawMesh.h | 3 +- Sofa/framework/Helper/CMakeLists.txt | 1 + .../Helper/src/sofa/helper/IotaView.h | 53 +++++++++++++++++++ Sofa/framework/Helper/test/CMakeLists.txt | 1 + Sofa/framework/Helper/test/IotaView_test.cpp | 44 +++++++++++++++ 6 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 Sofa/framework/Helper/src/sofa/helper/IotaView.h create mode 100644 Sofa/framework/Helper/test/IotaView_test.cpp diff --git a/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h b/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h index b2e75d143b9..cc2b7c647b2 100644 --- a/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h +++ b/Sofa/Component/SolidMechanics/FEM/HyperElastic/src/sofa/component/solidmechanics/fem/hyperelastic/TetrahedronHyperelasticityFEMDrawing.h @@ -116,7 +116,7 @@ void drawHyperelasticTets(const core::visual::VisualParams* vparams, core::topology::BaseMeshTopology* topology, const std::string& materialName) { - const auto indices = std::ranges::iota_view(static_cast(0), topology->getNbTetrahedra()); + const auto indices = sofa::helper::IotaView(static_cast(0), topology->getNbTetrahedra()); drawHyperelasticTets(vparams, x, topology, materialName, indices); } diff --git a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h index a8896838c08..3514ce48e50 100644 --- a/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h +++ b/Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -66,7 +67,7 @@ struct BaseDrawMesh const ColorContainer& colors = Derived::defaultColors) { const auto totalNbElements = topology->getNbElements(); - const auto elementsToDraw = std::ranges::iota_view(static_cast(0), totalNbElements); + const auto elementsToDraw = sofa::helper::IotaView(static_cast(0), totalNbElements); drawSomeElements(drawTool, position, topology, elementsToDraw, colors); } diff --git a/Sofa/framework/Helper/CMakeLists.txt b/Sofa/framework/Helper/CMakeLists.txt index 75767d7a130..5de5b85a719 100644 --- a/Sofa/framework/Helper/CMakeLists.txt +++ b/Sofa/framework/Helper/CMakeLists.txt @@ -70,6 +70,7 @@ set(HEADER_FILES ${SRC_ROOT}/hash.h ${SRC_ROOT}/init.h ${SRC_ROOT}/integer_id.h + ${SRC_ROOT}/IotaView.h ${SRC_ROOT}/accessor/ReadAccessor.h ${SRC_ROOT}/accessor/ReadAccessorFixedArray.h ${SRC_ROOT}/accessor/ReadAccessorVector.h diff --git a/Sofa/framework/Helper/src/sofa/helper/IotaView.h b/Sofa/framework/Helper/src/sofa/helper/IotaView.h new file mode 100644 index 00000000000..26ab73b751e --- /dev/null +++ b/Sofa/framework/Helper/src/sofa/helper/IotaView.h @@ -0,0 +1,53 @@ +#pragma once + +#include + +namespace sofa::helper +{ + +/** + * Simple alternative to std::ranges::iota_view, compatible with pre-C++20 + */ +template +class IotaView +{ +public: + struct iota_iterator + { + using value_type = T; + using difference_type = std::ptrdiff_t; + using iterator_category = std::forward_iterator_tag; + using reference = T&; + using pointer = T*; + + explicit iota_iterator(T val) : val_(val) {} + + T operator*() const { return val_; } + iota_iterator& operator++() { ++val_; return *this; } + bool operator!=(const iota_iterator& other) const { return val_ != other.val_; } + + private: + T val_; + }; + + using iterator = iota_iterator; + using value_type = T; + + IotaView(T start, T end) : m_start(start), m_end(end) {} + + iterator begin() const { return iterator(m_start); } + iterator end() const { return iterator(m_end); } + + [[nodiscard]] T size() const { return m_end - m_start; } + [[nodiscard]] T operator[](T i) const { return m_start + i; } + T front() const { return m_start; } + T back() const { return m_end - 1; } + [[nodiscard]] bool empty() const { return m_start == m_end; } + +private: + T m_start; + T m_end; +}; + + +} diff --git a/Sofa/framework/Helper/test/CMakeLists.txt b/Sofa/framework/Helper/test/CMakeLists.txt index b6120ff71b9..67aa4c3fe8b 100644 --- a/Sofa/framework/Helper/test/CMakeLists.txt +++ b/Sofa/framework/Helper/test/CMakeLists.txt @@ -5,6 +5,7 @@ project(Sofa.Helper_test) set(SOURCE_FILES DiffLib_test.cpp Factory_test.cpp + IotaView_test.cpp KdTree_test.cpp NameDecoder_test.cpp OptionsGroup_test.cpp diff --git a/Sofa/framework/Helper/test/IotaView_test.cpp b/Sofa/framework/Helper/test/IotaView_test.cpp new file mode 100644 index 00000000000..9e1d22b386e --- /dev/null +++ b/Sofa/framework/Helper/test/IotaView_test.cpp @@ -0,0 +1,44 @@ +#include +#include + +namespace sofa +{ + +TEST(IotaView, loop) +{ + const auto range = sofa::helper::IotaView{0, 10}; + + int i = 0; + for (const auto value : range) + { + EXPECT_EQ(value, i); + ++i; + } +} + +TEST(IotaView, empty) +{ + { + const auto range = sofa::helper::IotaView{0, 10}; + EXPECT_FALSE(range.empty()); + } + { + const auto range = sofa::helper::IotaView{0, 0}; + EXPECT_TRUE(range.empty()); + } +} + +TEST(IotaView, size) +{ + const auto range = sofa::helper::IotaView{0, 10}; + EXPECT_EQ(range.size(), 10); +} + +TEST(IotaView, access) +{ + const auto range = sofa::helper::IotaView{4, 10}; + EXPECT_EQ(range[0], 4); + EXPECT_EQ(range[9], 4+9); +} + +}