Skip to content

Commit cc263ef

Browse files
[Sofa.GUI.Common] Handle object selection in BaseViewer (#5636)
* Add a way to handle object selection in viewer. It is usefull to be able to handle the currently selected object in the viewer to implement visual feedbacks. This is done by adding a vector of selected node/object as well as a drawSelection method to do the rendering. * Replace std::vector with std::set * FIXUP * Add configuration parameters to control the selectionDrawing * Update BaseViewer.cpp Remove commented code. * Update BaseViewer.cpp Integrate comments * Update Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp Co-authored-by: Hugo <[email protected]> * Update Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp --------- Co-authored-by: Hugo <[email protected]>
1 parent 83ff017 commit cc263ef

File tree

2 files changed

+144
-0
lines changed

2 files changed

+144
-0
lines changed

Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,4 +277,129 @@ void BaseViewer::fitObjectBBox(sofa::core::objectmodel::BaseObject * object)
277277
redraw();
278278
}
279279

280+
void BaseViewer::drawSelection(sofa::core::visual::VisualParams* vparams)
281+
{
282+
assert(vparams && "call of drawSelection without a valid visual param is not allowed");
283+
284+
auto drawTool = vparams->drawTool();
285+
286+
if(currentSelection.empty())
287+
return;
288+
289+
drawTool->setPolygonMode(0, false);
290+
float screenHeight = vparams->viewport()[4];
291+
292+
for(auto current : currentSelection)
293+
{
294+
using sofa::type::Vec3;
295+
using sofa::type::RGBAColor;
296+
using sofa::defaulttype::RigidCoord;
297+
using sofa::defaulttype::Rigid3Types;
298+
299+
////////////////////// Render when the selection is a Node ///////////////////////////////
300+
auto node = castTo<sofa::simulation::Node*>(current.get());
301+
if(node && m_showSelectedNodeBoundingBox)
302+
{
303+
auto box = node->f_bbox.getValue();
304+
drawTool->drawBoundingBox(box.minBBox(), box.maxBBox(), 2.0);
305+
306+
// If it is a node... it is not a BaseObject, so we can continue.
307+
continue;
308+
}
309+
310+
////////////////////// Render when the selection is a BaseObject //////////////////////////
311+
auto object = castTo<sofa::core::objectmodel::BaseObject*>(current.get());
312+
if(object)
313+
{
314+
sofa::type::BoundingBox box;
315+
auto ownerNode = dynamic_cast<sofa::simulation::Node*>(object->getContext());
316+
if(ownerNode)
317+
{
318+
box = ownerNode->f_bbox.getValue();
319+
}
320+
321+
if(m_showSelectedObjectBoundingBox)
322+
{
323+
drawTool->drawBoundingBox(box.minBBox(), box.maxBBox(), 2.0);
324+
}
325+
326+
std::vector<Vec3> positions;
327+
auto position = object->findData("position");
328+
if(position)
329+
{
330+
auto positionsData = dynamic_cast<Data<sofa::type::vector<Vec3>>*>(position);
331+
if(positionsData)
332+
{
333+
positions = positionsData->getValue();
334+
if(m_showSelectedObjectBoundingBox){
335+
drawTool->drawPoints(positions, 2.0, RGBAColor::yellow());
336+
}
337+
}
338+
else
339+
{
340+
auto rigidPositions = dynamic_cast<Data<sofa::type::vector<RigidCoord<3, SReal>>>*>(position);
341+
if(rigidPositions)
342+
{
343+
for(auto frame : rigidPositions->getValue())
344+
{
345+
float targetScreenSize = 50.0;
346+
float distance = (currentCamera->getPosition() - Rigid3Types::getCPos(frame)).norm();
347+
SReal scale = distance * tan(currentCamera->getFieldOfView() / 2.0f) * targetScreenSize / screenHeight;
348+
drawTool->drawFrame(Rigid3Types::getCPos(frame), Rigid3Types::getCRot(frame), {scale, scale,scale});
349+
positions.push_back(Rigid3Types::getCPos(frame));
350+
}
351+
}
352+
}
353+
}
354+
355+
if(m_showSelectedObjectSurfaces && !positions.empty())
356+
{
357+
auto triangles = object->findData("triangles");
358+
if(triangles)
359+
{
360+
auto d_triangles = dynamic_cast<Data<sofa::type::vector<core::topology::Topology::Triangle>>*>(triangles);
361+
if(d_triangles)
362+
{
363+
std::vector<Vec3> tripoints;
364+
for(auto indices : d_triangles->getValue())
365+
{
366+
if(indices[0] < positions.size() &&
367+
indices[1] < positions.size() &&
368+
indices[2] < positions.size())
369+
{
370+
tripoints.push_back(positions[indices[0]]);
371+
tripoints.push_back(positions[indices[1]]);
372+
tripoints.push_back(positions[indices[1]]);
373+
tripoints.push_back(positions[indices[2]]);
374+
tripoints.push_back(positions[indices[2]]);
375+
tripoints.push_back(positions[indices[0]]);
376+
}
377+
}
378+
drawTool->drawLines(tripoints, 1.5, RGBAColor::fromFloat(1.0,1.0,1.0,0.7));
379+
}
380+
}
381+
}
382+
383+
if(!positions.empty() && m_showSelectedObjectIndices)
384+
{
385+
const float scale = (box.maxBBox() - box.minBBox()).norm() * m_visualScaling;
386+
drawTool->draw3DText_Indices(positions, scale, RGBAColor::white());
387+
}
388+
389+
continue;
390+
}
391+
msg_error("BaseViewer") << "Only node and object can be selected, if you see this line please report to sofa-developement team";
392+
}
393+
}
394+
395+
void BaseViewer::setCurrentSelection(const std::set<sofa::core::objectmodel::Base::SPtr>& selection)
396+
{
397+
currentSelection = selection;
398+
}
399+
400+
const std::set<core::objectmodel::Base::SPtr> &BaseViewer::getCurrentSelection() const
401+
{
402+
return currentSelection;
403+
}
404+
280405
} // namespace sofa::gui::common

Sofa/GUI/Common/src/sofa/gui/common/BaseViewer.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,23 @@ class SOFA_GUI_COMMON_API BaseViewer
121121
/// the rendering pass is done here (have to be called in a loop)
122122
virtual void drawScene(void) = 0;
123123

124+
void drawSelection(sofa::core::visual::VisualParams* vparams);
125+
126+
void setCurrentSelection(const std::set<core::objectmodel::Base::SPtr> &selection);
127+
const std::set<sofa::core::objectmodel::Base::SPtr>& getCurrentSelection() const;
128+
129+
public:
130+
bool m_showSelectedNodeBoundingBox {true};
131+
bool m_showSelectedObjectBoundingBox {true};
132+
bool m_showSelectedObjectPositions {true};
133+
bool m_showSelectedObjectSurfaces {true};
134+
bool m_showSelectedObjectVolumes {true};
135+
bool m_showSelectedObjectIndices {true};
136+
float m_visualScaling {0.2};
137+
124138
protected:
139+
void drawIndices(const sofa::type::BoundingBox& bbox, const std::vector<sofa::type::Vec3>& positions);
140+
125141
/// internally called while the actual viewer needs a redraw (ie the camera changed)
126142
virtual void redraw() = 0;
127143

@@ -135,6 +151,7 @@ class SOFA_GUI_COMMON_API BaseViewer
135151
bool _video;
136152
bool m_isVideoButtonPressed;
137153
bool m_bShowAxis;
154+
138155
bool _fullScreen;
139156
int _background;
140157
bool initTexturesDone;
@@ -153,6 +170,8 @@ class SOFA_GUI_COMMON_API BaseViewer
153170
int _mouseInteractorSavedPosY;
154171

155172
std::string _screenshotDirectory;
173+
174+
std::set<sofa::core::objectmodel::Base::SPtr> currentSelection;
156175
};
157176

158177
} // namespace sofa::gui::common

0 commit comments

Comments
 (0)