Skip to content

Commit 2992288

Browse files
committed
Add support for selecting and deselecting bodies via mouse pick
1 parent 9e15e30 commit 2992288

File tree

5 files changed

+506
-62
lines changed

5 files changed

+506
-62
lines changed

demos/rlCollisionDemo/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ if(QT_FOUND AND SoQt_FOUND AND (RL_BUILD_SG_BULLET OR RL_BUILD_SG_FCL OR RL_BUIL
2626
BodyModel.h
2727
MainWindow.h
2828
SoGradientBackground.h
29+
SoMaterialHighlightRenderAction.h
2930
)
3031

3132
set(
@@ -35,6 +36,7 @@ if(QT_FOUND AND SoQt_FOUND AND (RL_BUILD_SG_BULLET OR RL_BUILD_SG_FCL OR RL_BUIL
3536
MainWindow.cpp
3637
rlCollisionDemo.cpp
3738
SoGradientBackground.cpp
39+
SoMaterialHighlightRenderAction.cpp
3840
)
3941

4042
add_executable(

demos/rlCollisionDemo/MainWindow.cpp

+114-59
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,21 @@
3131
#include <QMessageBox>
3232
#include <QTableView>
3333
#include <QStatusBar>
34+
#include <Inventor/SoPickedPoint.h>
3435
#include <Inventor/nodes/SoDrawStyle.h>
3536
#include <Inventor/Qt/SoQt.h>
3637
#include <Inventor/VRMLnodes/SoVRMLAppearance.h>
3738
#include <Inventor/VRMLnodes/SoVRMLMaterial.h>
38-
#include <Inventor/VRMLnodes/SoVRMLShape.h>
39+
#include <Inventor/VRMLnodes/SoVRMLTransform.h>
3940
#include <rl/sg/Body.h>
4041
#include <rl/sg/DepthScene.h>
4142
#include <rl/sg/DistanceScene.h>
4243
#include <rl/sg/Model.h>
4344
#include <rl/sg/Shape.h>
4445
#include <rl/sg/SimpleScene.h>
4546
#include <rl/sg/XmlFactory.h>
47+
#include <rl/sg/so/Body.h>
48+
#include <rl/sg/so/Shape.h>
4649

4750
#if QT_VERSION >= 0x050200
4851
#include <QCommandLineParser>
@@ -68,12 +71,13 @@
6871
#include "BodyModel.h"
6972
#include "MainWindow.h"
7073
#include "SoGradientBackground.h"
74+
#include "SoMaterialHighlightRenderAction.h"
7175

7276
MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f) :
7377
QMainWindow(parent, f),
7478
collisionScene(),
7579
viewScene(),
76-
body(0),
80+
bodyModel(new BodyModel(this)),
7781
depthCoordinate(nullptr),
7882
depthLabel(new QLabel(this)),
7983
depthLineSet(nullptr),
@@ -85,15 +89,23 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f) :
8589
engine(),
8690
filename(),
8791
gradientBackground(),
88-
model(0),
92+
highlightRenderAction(nullptr),
93+
root(nullptr),
94+
selected(nullptr),
95+
selection(nullptr),
8996
simpleLabel(new QLabel(this)),
97+
view2collision(),
9098
viewer(nullptr)
9199
{
92100
MainWindow::singleton = this;
93101

94102
SoQt::init(this);
95103
SoDB::init();
96104
SoGradientBackground::initClass();
105+
SoMaterialHighlightRenderAction::initClass();
106+
107+
this->root = new SoSeparator();
108+
this->root->ref();
97109

98110
this->parseCommandLine();
99111

@@ -145,11 +157,22 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f) :
145157
this->gradientBackground->ref();
146158
this->gradientBackground->color0.setValue(0.8f, 0.8f, 0.8f);
147159
this->gradientBackground->color1.setValue(1.0f, 1.0f, 1.0f);
148-
this->viewScene->root->insertChild(this->gradientBackground, 0);
160+
this->root->insertChild(this->gradientBackground, 0);
161+
162+
this->selection = new SoSelection();
163+
this->selection->addSelectionCallback(MainWindow::selectionCallback, this);
164+
this->selection->addDeselectionCallback(MainWindow::deselectionCallback, this);
165+
this->selection->setPickFilterCallback(MainWindow::pickFilterCallback, this);
166+
this->selection->policy = SoSelection::SINGLE;
167+
this->selection->addChild(this->viewScene->root);
168+
this->root->addChild(this->selection);
169+
170+
this->highlightRenderAction = new SoMaterialHighlightRenderAction();
149171

150172
this->viewer = new SoQtExaminerViewer(this, nullptr, true, SoQtFullViewer::BUILD_POPUP);
151173
this->viewer->setFeedbackVisibility(true);
152-
this->viewer->setSceneGraph(this->viewScene->root);
174+
this->viewer->setGLRenderAction(this->highlightRenderAction);
175+
this->viewer->setSceneGraph(this->root);
153176
this->viewer->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_BLEND);
154177

155178
this->setCentralWidget(this->viewer->getWidget());
@@ -161,16 +184,18 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f) :
161184
factory.load(this->filename.toStdString(), this->collisionScene.get());
162185
factory.load(this->filename.toStdString(), this->viewScene.get());
163186

187+
for (rl::sg::Scene::Iterator i = this->viewScene->begin(), j = this->collisionScene->begin(); i != this->viewScene->end(); ++i, ++j)
188+
{
189+
for (rl::sg::Model::Iterator k = (*i)->begin(), l = (*j)->begin(); k != (*i)->end(); ++k, ++l)
190+
{
191+
this->view2collision[*k] = *l;
192+
}
193+
}
194+
164195
this->viewer->viewAll();
165196

166197
BodyDelegate* bodyDelegate = new BodyDelegate(this);
167198

168-
BodyModel* bodyModel = new BodyModel(this);
169-
bodyModel->setBody(
170-
this->viewScene->getModel(this->model)->getBody(this->body),
171-
this->collisionScene->getModel(this->model)->getBody(this->body)
172-
);
173-
174199
QTableView* bodyView = new QTableView(this);
175200
#if QT_VERSION >= 0x050000
176201
bodyView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
@@ -180,14 +205,14 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f) :
180205
bodyView->horizontalHeader()->hide();
181206
bodyView->setAlternatingRowColors(true);
182207
bodyView->setItemDelegate(bodyDelegate);
183-
bodyView->setModel(bodyModel);
208+
bodyView->setModel(this->bodyModel);
184209

185210
QDockWidget* bodyDockWidget = new QDockWidget(this);
186211
bodyDockWidget->resize(160, 240);
187212
bodyDockWidget->setFeatures(QDockWidget::NoDockWidgetFeatures | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
188213
bodyDockWidget->setFloating(true);
189214
bodyDockWidget->setWidget(bodyView);
190-
bodyDockWidget->setWindowTitle("Model[" + QString::number(this->model) + "]->Body[" + QString::number(this->body) + "]");
215+
bodyDockWidget->setWindowTitle("Body");
191216

192217
SoDrawStyle* drawStyle = new SoDrawStyle();
193218
drawStyle->lineWidth = 0.0f;
@@ -253,15 +278,36 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f) :
253278
this->statusBar()->addWidget(this->depthLabel);
254279
}
255280

281+
if (this->viewScene->getNumModels() > 0)
282+
{
283+
rl::sg::Model* model = this->viewScene->getModel(0);
284+
285+
if (model->getNumBodies() > 0)
286+
{
287+
rl::sg::Body* body = model->getBody(0);
288+
this->selection->select(dynamic_cast<rl::sg::so::Body*>(body)->root);
289+
}
290+
}
291+
256292
this->test();
257293
}
258294

259295
MainWindow::~MainWindow()
260296
{
261-
this->gradientBackground->unref();
297+
this->root->unref();
262298
MainWindow::singleton = nullptr;
263299
}
264300

301+
void
302+
MainWindow::deselectionCallback(void* data, SoPath* path)
303+
{
304+
MainWindow* mainWindow = static_cast<MainWindow*>(data);
305+
mainWindow->bodyModel->setBody(nullptr, nullptr);
306+
mainWindow->selected = nullptr;
307+
mainWindow->selection->touch();
308+
mainWindow->test();
309+
}
310+
265311
MainWindow*
266312
MainWindow::instance()
267313
{
@@ -300,30 +346,15 @@ MainWindow::parseCommandLine()
300346
engines.sort();
301347

302348
#if QT_VERSION >= 0x050200
303-
QCommandLineOption bodyOption(QStringList("body"), "Sets active body.", "body");
304349
QCommandLineOption engineOption(QStringList("engine"), "Sets collision engine.", engines.join("|"));
305-
QCommandLineOption modelOption(QStringList("model"), "Sets model of active body.", "model");
306350

307351
QCommandLineParser parser;
308-
parser.addOption(bodyOption);
309352
parser.addOption(engineOption);
310353
const QCommandLineOption helpOption = parser.addHelpOption();
311-
parser.addOption(modelOption);
312354
parser.addPositionalArgument("filename", "", "[filename]");
313355

314356
parser.process(QCoreApplication::arguments());
315357

316-
if (parser.isSet(bodyOption))
317-
{
318-
bool ok;
319-
this->body = parser.value(bodyOption).toUInt(&ok);
320-
321-
if (!ok)
322-
{
323-
parser.showHelp();
324-
}
325-
}
326-
327358
if (parser.isSet(engineOption))
328359
{
329360
QString engine = parser.value(engineOption);
@@ -336,17 +367,6 @@ MainWindow::parseCommandLine()
336367
this->engine = engine;
337368
}
338369

339-
if (parser.isSet(modelOption))
340-
{
341-
bool ok;
342-
this->model = parser.value(modelOption).toUInt(&ok);
343-
344-
if (!ok)
345-
{
346-
parser.showHelp();
347-
}
348-
}
349-
350370
if (parser.positionalArguments().size() > 1)
351371
{
352372
parser.showHelp();
@@ -357,30 +377,20 @@ MainWindow::parseCommandLine()
357377
this->filename = parser.positionalArguments()[0];
358378
}
359379
#else
360-
QRegExp bodyRegExp("--body=(\\d*)");
361380
QRegExp engineRegExp("--engine=(" + engines.join("|") + ")");
362381
QRegExp helpRegExp("--help");
363-
QRegExp modelRegExp("--model=(\\d*)");
364382

365383
for (int i = 1; i < QApplication::arguments().size(); ++i)
366384
{
367-
if (-1 != bodyRegExp.indexIn(QApplication::arguments()[i]))
368-
{
369-
this->body = bodyRegExp.cap(1).toUInt();
370-
}
371-
else if (-1 != engineRegExp.indexIn(QApplication::arguments()[i]))
385+
if (-1 != engineRegExp.indexIn(QApplication::arguments()[i]))
372386
{
373387
this->engine = engineRegExp.cap(1);
374388
}
375389
else if (-1 != helpRegExp.indexIn(QApplication::arguments()[i]))
376390
{
377-
QMessageBox::information(this, "Usage", "rlCollisionDemo [--body=<body>] [--engine=<" + engines.join("|") + ">] [--help] [--model=<model>] [filename]");
391+
QMessageBox::information(this, "Usage", "rlCollisionDemo [--engine=<" + engines.join("|") + ">] [--help] [filename]");
378392
exit(0);
379393
}
380-
else if (-1 != modelRegExp.indexIn(QApplication::arguments()[i]))
381-
{
382-
this->model = modelRegExp.cap(1).toUInt();
383-
}
384394
else
385395
{
386396
this->filename = QApplication::arguments()[i];
@@ -389,6 +399,38 @@ MainWindow::parseCommandLine()
389399
#endif
390400
}
391401

402+
SoPath*
403+
MainWindow::pickFilterCallback(void* data, const SoPickedPoint* pick)
404+
{
405+
SoFullPath* path = static_cast<SoFullPath*>(pick->getPath());
406+
path->pop();
407+
path->pop();
408+
path->pop();
409+
return path;
410+
}
411+
412+
void
413+
MainWindow::selectionCallback(void* data, SoPath* path)
414+
{
415+
MainWindow* mainWindow = static_cast<MainWindow*>(data);
416+
417+
if (path->getTail()->isOfType(SoVRMLTransform::getClassTypeId()))
418+
{
419+
SoVRMLTransform* vrmlTransform = static_cast<SoVRMLTransform*>(path->getTail());
420+
421+
if (nullptr != vrmlTransform->getUserData())
422+
{
423+
rl::sg::so::Body* view = static_cast<rl::sg::so::Body*>(vrmlTransform->getUserData());
424+
rl::sg::Body* collision = dynamic_cast<rl::sg::Body*>(mainWindow->view2collision[view]);
425+
mainWindow->bodyModel->setBody(collision, view);
426+
mainWindow->selected = view;
427+
}
428+
}
429+
430+
mainWindow->selection->touch();
431+
mainWindow->test();
432+
}
433+
392434
void
393435
MainWindow::test()
394436
{
@@ -400,7 +442,17 @@ MainWindow::test()
400442
this->depthLineSet->coordIndex.setNum(0);
401443
this->depthCoordinate->point.setNum(0);
402444

403-
rl::sg::Body* body = this->collisionScene->getModel(this->model)->getBody(this->body);
445+
rl::sg::Base* collision = this->view2collision[this->selected];
446+
447+
if (nullptr == this->selected || nullptr == collision)
448+
{
449+
this->simpleLabel->hide();
450+
this->distanceLabel->hide();
451+
this->depthLabel->hide();
452+
return;
453+
}
454+
455+
rl::sg::Body* body = dynamic_cast<rl::sg::Body*>(collision);
404456

405457
if (rl::sg::SimpleScene* simpleScene = dynamic_cast<rl::sg::SimpleScene*>(this->collisionScene.get()))
406458
{
@@ -420,19 +472,20 @@ MainWindow::test()
420472
}
421473
}
422474

475+
this->simpleLabel->show();
423476
this->simpleLabel->setText("Collisions: " + QString::number(collisions));
424477

425478
if (collisions > 0)
426479
{
427-
this->viewer->setBackgroundColor(SbColor(0.5, 0, 0));
428-
this->gradientBackground->color0.setValue(0.5f, 0.0f, 0.0f);
429-
this->gradientBackground->color1.setValue(1.0f, 1.0f, 1.0f);
480+
this->highlightRenderAction->setDiffuseColor(SbColor(0.8f, 0.0f, 0.0f));
481+
this->highlightRenderAction->setEmissiveColor(SbColor(0.25f, 0.0f, 0.0f));
482+
this->highlightRenderAction->setSpecularColor(SbColor(1.0f, 0.0f, 0.0f));
430483
}
431484
else
432485
{
433-
this->viewer->setBackgroundColor(SbColor(0, 0, 0));
434-
this->gradientBackground->color0.setValue(0.8f, 0.8f, 0.8f);
435-
this->gradientBackground->color1.setValue(1.0f, 1.0f, 1.0f);
486+
this->highlightRenderAction->setDiffuseColor(SbColor(0.8f, 0.8f, 0.8f));
487+
this->highlightRenderAction->setEmissiveColor(SbColor(0.0f, 0.0f, 0.25f));
488+
this->highlightRenderAction->setSpecularColor(SbColor(0.0f, 0.0f, 1.0f));
436489
}
437490
}
438491

@@ -462,6 +515,7 @@ MainWindow::test()
462515
}
463516
}
464517

518+
this->distanceLabel->show();
465519
this->distanceLabel->setText("Distance: " + QString::number(distance));
466520

467521
if (distance > 0 && distance < std::numeric_limits<rl::math::Real>::max())
@@ -520,6 +574,7 @@ MainWindow::test()
520574
}
521575
}
522576

577+
this->depthLabel->show();
523578
this->depthLabel->setText("Depth: " + QString::number(depth));
524579

525580
if (depth > 0)

0 commit comments

Comments
 (0)