diff --git a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp index 5e1f9f18c2d..bf49cf20e36 100644 --- a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp +++ b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp @@ -277,4 +277,129 @@ void BaseViewer::fitObjectBBox(sofa::core::objectmodel::BaseObject * object) redraw(); } +void BaseViewer::drawSelection(sofa::core::visual::VisualParams* vparams) +{ + assert(vparams && "call of drawSelection without a valid visual param is not allowed"); + + auto drawTool = vparams->drawTool(); + + if(currentSelection.empty()) + return; + + drawTool->setPolygonMode(0, false); + float screenHeight = vparams->viewport()[4]; + + for(auto current : currentSelection) + { + using sofa::type::Vec3; + using sofa::type::RGBAColor; + using sofa::defaulttype::RigidCoord; + using sofa::defaulttype::Rigid3Types; + + ////////////////////// Render when the selection is a Node /////////////////////////////// + auto node = castTo(current.get()); + if(node && m_showSelectedNodeBoundingBox) + { + auto box = node->f_bbox.getValue(); + drawTool->drawBoundingBox(box.minBBox(), box.maxBBox(), 2.0); + + // If it is a node... it is not a BaseObject, so we can continue. + continue; + } + + ////////////////////// Render when the selection is a BaseObject ////////////////////////// + auto object = castTo(current.get()); + if(object) + { + sofa::type::BoundingBox box; + auto ownerNode = dynamic_cast(object->getContext()); + if(ownerNode) + { + box = ownerNode->f_bbox.getValue(); + } + + if(m_showSelectedObjectBoundingBox) + { + drawTool->drawBoundingBox(box.minBBox(), box.maxBBox(), 2.0); + } + + std::vector positions; + auto position = object->findData("position"); + if(position) + { + auto positionsData = dynamic_cast>*>(position); + if(positionsData) + { + positions = positionsData->getValue(); + if(m_showSelectedObjectBoundingBox){ + drawTool->drawPoints(positions, 2.0, RGBAColor::yellow()); + } + } + else + { + auto rigidPositions = dynamic_cast>>*>(position); + if(rigidPositions) + { + for(auto frame : rigidPositions->getValue()) + { + float targetScreenSize = 50.0; + float distance = (currentCamera->getPosition() - Rigid3Types::getCPos(frame)).norm(); + SReal scale = distance * tan(currentCamera->getFieldOfView() / 2.0f) * targetScreenSize / screenHeight; + drawTool->drawFrame(Rigid3Types::getCPos(frame), Rigid3Types::getCRot(frame), {scale, scale,scale}); + positions.push_back(Rigid3Types::getCPos(frame)); + } + } + } + } + + if(m_showSelectedObjectSurfaces && !positions.empty()) + { + auto triangles = object->findData("triangles"); + if(triangles) + { + auto d_triangles = dynamic_cast>*>(triangles); + if(d_triangles) + { + std::vector tripoints; + for(auto indices : d_triangles->getValue()) + { + 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, 1.5, RGBAColor::fromFloat(1.0,1.0,1.0,0.7)); + } + } + } + + if(!positions.empty() && m_showSelectedObjectIndices) + { + const float scale = (box.maxBBox() - box.minBBox()).norm() * m_visualScaling; + drawTool->draw3DText_Indices(positions, scale, RGBAColor::white()); + } + + continue; + } + msg_error("BaseViewer") << "Only node and object can be selected, if you see this line please report to sofa-developement team"; + } +} + +void BaseViewer::setCurrentSelection(const std::set& selection) +{ + currentSelection = selection; +} + +const std::set &BaseViewer::getCurrentSelection() const +{ + return currentSelection; +} + } // namespace sofa::gui::common diff --git a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h index 6fb448907b4..356485fc0c7 100644 --- a/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h +++ b/Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h @@ -121,7 +121,23 @@ 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 setCurrentSelection(const std::set &selection); + const std::set& getCurrentSelection() const; + +public: + bool m_showSelectedNodeBoundingBox {true}; + bool m_showSelectedObjectBoundingBox {true}; + bool m_showSelectedObjectPositions {true}; + bool m_showSelectedObjectSurfaces {true}; + bool m_showSelectedObjectVolumes {true}; + bool m_showSelectedObjectIndices {true}; + float m_visualScaling {0.2}; + protected: + void drawIndices(const sofa::type::BoundingBox& bbox, const std::vector& positions); + /// internally called while the actual viewer needs a redraw (ie the camera changed) virtual void redraw() = 0; @@ -135,6 +151,7 @@ class SOFA_GUI_COMMON_API BaseViewer bool _video; bool m_isVideoButtonPressed; bool m_bShowAxis; + bool _fullScreen; int _background; bool initTexturesDone; @@ -153,6 +170,8 @@ class SOFA_GUI_COMMON_API BaseViewer int _mouseInteractorSavedPosY; std::string _screenshotDirectory; + + std::set currentSelection; }; } // namespace sofa::gui::common