GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/node.cpp Lines: 223 438 50.9 %
Date: 2023-03-14 11:04:37 Branches: 223 650 34.3 %

Line Branch Exec Source
1
//
2
//  node.cpp
3
//  gepetto-viewer
4
//
5
//  Created by Justin Carpentier, Mathieu Geisert in November 2014.
6
//  Copyright (c) 2014 LAAS-CNRS. All rights reserved.
7
//
8
9
#include <gepetto/viewer/node-visitor.h>
10
#include <gepetto/viewer/node.h>
11
#include <gepetto/viewer/window-manager.h>
12
13
#include <climits>
14
#include <osg/LineWidth>
15
#include <osg/Material>
16
#include <osgFX/Outline>
17
#include <osgFX/Scribe>
18
19
#include "log.hh"
20
21
namespace gepetto {
22
namespace viewer {
23
namespace {
24
const osg::StateSetRefPtr& getVisibleStateSet(const LightingMode& mode) {
25
  static osg::StateSetRefPtr ssOn, ssOff;
26
  switch (mode) {
27
    case LIGHT_INFLUENCE_ON:
28
      if (false && !ssOn) {  // Disable because this is the default.
29
        ssOn = osg::StateSetRefPtr(new osg::StateSet());
30
        ssOn->setRenderBinToInherit();
31
        ssOn->setMode(GL_DEPTH_TEST, ::osg::StateAttribute::ON |
32
                                         ::osg::StateAttribute::PROTECTED);
33
        ssOn->setMode(GL_CULL_FACE, ::osg::StateAttribute::OFF |
34
                                        ::osg::StateAttribute::PROTECTED);
35
        ssOn->setMode(GL_LIGHTING, ::osg::StateAttribute::ON |
36
                                       ::osg::StateAttribute::PROTECTED);
37
      }
38
      return ssOn;
39
    case LIGHT_INFLUENCE_OFF:
40
      if (!ssOff) {
41
        ssOff = osg::StateSetRefPtr(new osg::StateSet());
42
        ssOff->setRenderBinToInherit();
43
        ssOff->setMode(GL_DEPTH_TEST, ::osg::StateAttribute::ON |
44
                                          ::osg::StateAttribute::PROTECTED);
45
        ssOff->setMode(GL_CULL_FACE, ::osg::StateAttribute::OFF |
46
                                         ::osg::StateAttribute::PROTECTED);
47
        ssOff->setMode(GL_LIGHTING, ::osg::StateAttribute::OFF |
48
                                        ::osg::StateAttribute::PROTECTED);
49
      }
50
      return ssOff;
51
    default:
52
      ASSERT(false, "LightingMode is not well defined");
53
      break;
54
  };
55
}
56
57
const osg::StateSetRefPtr& getAlwaysOnTopStateSet(const LightingMode& mode) {
58
  static osg::StateSetRefPtr ssOn, ssOff;
59
  switch (mode) {
60
    case LIGHT_INFLUENCE_ON:
61
      if (!ssOn) {  // Disable because this is the default.
62
        ssOn = osg::StateSetRefPtr(new osg::StateSet());
63
        ssOn->setRenderBinDetails(INT_MAX, "DepthSortedBin");
64
        ssOn->setMode(GL_DEPTH_TEST, ::osg::StateAttribute::OFF |
65
                                         ::osg::StateAttribute::PROTECTED);
66
        ssOn->setMode(GL_CULL_FACE, ::osg::StateAttribute::ON |
67
                                        ::osg::StateAttribute::PROTECTED);
68
        ssOn->setMode(GL_LIGHTING, ::osg::StateAttribute::ON |
69
                                       ::osg::StateAttribute::PROTECTED);
70
      }
71
      return ssOn;
72
    case LIGHT_INFLUENCE_OFF:
73
      if (!ssOff) {
74
        ssOff = osg::StateSetRefPtr(new osg::StateSet());
75
        ssOff->setRenderBinDetails(INT_MAX, "DepthSortedBin");
76
        ssOff->setMode(GL_DEPTH_TEST, ::osg::StateAttribute::OFF |
77
                                          ::osg::StateAttribute::PROTECTED);
78
        ssOff->setMode(GL_CULL_FACE, ::osg::StateAttribute::ON |
79
                                         ::osg::StateAttribute::PROTECTED);
80
        ssOff->setMode(GL_LIGHTING, ::osg::StateAttribute::OFF |
81
                                        ::osg::StateAttribute::PROTECTED);
82
      }
83
      return ssOff;
84
    default:
85
      ASSERT(false, "LightingMode is not well defined");
86
      break;
87
  };
88
}
89
90
1
const osg::StateSetRefPtr& getWireframeStateSet() {
91

1
  static osg::StateSetRefPtr ss;
92
1
  if (!ss) {
93

1
    ss = osg::StateSetRefPtr(new osg::StateSet());
94
95
    /* Allowing wireframe mode */
96

2
    osg::PolygonModeRefPtr polygon_mode_ptr = new ::osg::PolygonMode;
97
1
    polygon_mode_ptr->setMode(::osg::PolygonMode::FRONT_AND_BACK,
98
                              ::osg::PolygonMode::LINE);
99
1
    polygon_mode_ptr->setDataVariance(osg::Object::STATIC);
100
101

2
    ::osg::MaterialRefPtr material_wireframe_ptr = new osg::Material;
102
1
    material_wireframe_ptr->setColorMode(osg::Material::DIFFUSE);
103
2
    material_wireframe_ptr->setDiffuse(osg::Material::FRONT_AND_BACK,
104
1
                                       osgVector4(1., 1., 1., 1.));
105
1
    material_wireframe_ptr->setDataVariance(osg::Object::STATIC);
106
107
1
    ss->setMode(
108
        GL_BLEND,
109
        ::osg::StateAttribute::OFF |
110
            ::osg::StateAttribute::PROTECTED);  // PROTECTED attribut allows
111
                                                // wireframe node to not be
112
                                                // influenced by alpha
113
1
    ss->setAttributeAndModes(
114
        polygon_mode_ptr,
115
        ::osg::StateAttribute::PROTECTED | ::osg::StateAttribute::ON);
116
1
    ss->setAttributeAndModes(
117
        material_wireframe_ptr,
118
        ::osg::StateAttribute::ON | ::osg::StateAttribute::PROTECTED);
119
  }
120
1
  return ss;
121
}
122
123
template <unsigned int state>
124
12
const osg::StateSetRefPtr& getHighlightStateSet() {
125

12
  static osg::StateSetRefPtr ss;
126
  if (state == 0) return ss;
127
12
  if (!ss) {
128

12
    ss = osg::StateSetRefPtr(new osg::StateSet());
129

24
    ::osg::MaterialRefPtr material_switch_ptr = new osg::Material;
130
12
    int glModeValue = ::osg::StateAttribute::INHERIT;
131
    /// Some color codes are taken from
132
    /// http://devernay.free.fr/cours/opengl/materials.html
133
    switch (state) {
134
      case 1:  /// collision
135
2
        glModeValue =
136
            ::osg::StateAttribute::ON | ::osg::StateAttribute::OVERRIDE;
137
2
        material_switch_ptr->setColorMode(osg::Material::AMBIENT);
138
2
        material_switch_ptr->setDiffuse(osg::Material::FRONT_AND_BACK,
139
                                        osgVector4(1.0f, 0.f, 0.f, 1.f));
140
2
        material_switch_ptr->setTransparency(osg::Material::FRONT_AND_BACK,
141
                                             0.5f);
142
2
        break;
143
      case 2:  /// selection
144
2
        glModeValue = ::osg::StateAttribute::ON |
145
                      ::osg::StateAttribute::OVERRIDE |
146
                      ::osg::StateAttribute::PROTECTED;
147
        /// Blue
148
2
        material_switch_ptr->setAmbient(osg::Material::FRONT_AND_BACK,
149
                                        osgVector4(0.f, 0.f, 0.f, 1.f));
150
2
        material_switch_ptr->setDiffuse(osg::Material::FRONT_AND_BACK,
151
                                        osgVector4(0.f, 0.f, 1.f, 1.f));
152
2
        material_switch_ptr->setSpecular(osg::Material::FRONT_AND_BACK,
153
                                         osgVector4(0.6f, 0.6f, 0.7f, 1.f));
154
2
        material_switch_ptr->setShininess(osg::Material::FRONT_AND_BACK, 128.f);
155
2
        break;
156
      case 3:  /// selection
157
2
        glModeValue = ::osg::StateAttribute::ON |
158
                      ::osg::StateAttribute::OVERRIDE |
159
                      ::osg::StateAttribute::PROTECTED;
160
        /// Red
161
2
        material_switch_ptr->setAmbient(osg::Material::FRONT_AND_BACK,
162
                                        osgVector4(0.f, 0.f, 0.f, 1.f));
163
2
        material_switch_ptr->setDiffuse(osg::Material::FRONT_AND_BACK,
164
                                        osgVector4(1.0f, 0.f, 0.f, 1.f));
165
2
        material_switch_ptr->setSpecular(osg::Material::FRONT_AND_BACK,
166
                                         osgVector4(0.7f, 0.6f, 0.6f, 1.f));
167
2
        material_switch_ptr->setShininess(osg::Material::FRONT_AND_BACK, 96.f);
168
2
        break;
169
      case 4:  /// selection
170
2
        glModeValue = ::osg::StateAttribute::ON |
171
                      ::osg::StateAttribute::OVERRIDE |
172
                      ::osg::StateAttribute::PROTECTED;
173
        /// Red plastic
174
2
        material_switch_ptr->setAmbient(osg::Material::FRONT_AND_BACK,
175
                                        osgVector4(0.f, 0.f, 0.f, 1.f));
176
2
        material_switch_ptr->setDiffuse(osg::Material::FRONT_AND_BACK,
177
                                        osgVector4(0.5f, 0.f, 0.f, 1.f));
178
2
        material_switch_ptr->setSpecular(osg::Material::FRONT_AND_BACK,
179
                                         osgVector4(0.7f, 0.6f, 0.6f, 1.f));
180
2
        material_switch_ptr->setShininess(osg::Material::FRONT_AND_BACK, 32.f);
181
2
        break;
182
      case 5:  /// selection
183
2
        glModeValue = ::osg::StateAttribute::ON |
184
                      ::osg::StateAttribute::OVERRIDE |
185
                      ::osg::StateAttribute::PROTECTED;
186
        /// Bronze
187
2
        material_switch_ptr->setAmbient(
188
            osg::Material::FRONT_AND_BACK,
189
            osgVector4(0.2125f, 0.1275f, 0.054f, 1.f));
190
2
        material_switch_ptr->setDiffuse(
191
            osg::Material::FRONT_AND_BACK,
192
            osgVector4(0.714f, 0.4284f, 0.18144f, 1.f));
193
2
        material_switch_ptr->setSpecular(
194
            osg::Material::FRONT_AND_BACK,
195
            osgVector4(0.393548f, 0.271906f, 0.166721f, 1.f));
196
2
        material_switch_ptr->setShininess(osg::Material::FRONT_AND_BACK, 26.f);
197
2
        break;
198
      case 6:  /// selection
199
2
        glModeValue = ::osg::StateAttribute::ON |
200
                      ::osg::StateAttribute::OVERRIDE |
201
                      ::osg::StateAttribute::PROTECTED;
202
        /// Red rubber
203
2
        material_switch_ptr->setAmbient(osg::Material::FRONT_AND_BACK,
204
                                        osgVector4(0.05f, 0.f, 0.f, 1.f));
205
2
        material_switch_ptr->setDiffuse(osg::Material::FRONT_AND_BACK,
206
                                        osgVector4(0.5f, 0.5f, 0.4f, 1.f));
207
2
        material_switch_ptr->setSpecular(osg::Material::FRONT_AND_BACK,
208
                                         osgVector4(0.7f, 0.04f, 0.04f, 1.f));
209
2
        material_switch_ptr->setShininess(osg::Material::FRONT_AND_BACK, 10.f);
210
2
        break;
211
      default:
212
        ASSERT(false, "HighlightState is not well defined");
213
        break;
214
    }
215
12
    material_switch_ptr->setDataVariance(osg::Object::STATIC);
216
12
    ss->setAttributeAndModes(material_switch_ptr, glModeValue);
217
  }
218
12
  return ss;
219
}
220
221
int getNodeVisibilityMode(Node* node) { return node->getVisibilityMode(); }
222
void setNodeVisibilityMode(Node* node, const int& v) {
223
  node->setVisibilityMode((VisibilityMode)v);
224
}
225
226
int getNodeWireFrameMode(Node* node) { return node->getWireFrameMode(); }
227
void setNodeWireFrameMode(Node* node, const int& v) {
228
  node->setWireFrameMode((WireFrameMode)v);
229
}
230
231
int getNodeLightingMode(Node* node) { return node->getLightingMode(); }
232
void setNodeLightingMode(Node* node, const int& v) {
233
  node->setLightingMode((LightingMode)v);
234
}
235
236
void setNodeLandmark(Node* node, bool enable) {
237
  if (enable)
238
    node->addLandmark(0.05f);
239
  else
240
    node->deleteLandmark();
241
}
242
243
int getNodeHighlightState(Node* node) { return (int)node->getHighlightState(); }
244
void setNodeHighlightState(Node* node, const int& v) {
245
  node->setHighlightState(v);
246
}
247
248
void setFlag(::osg::Node* node, osg::Node::NodeMask bit, bool on) {
249
  if (on)
250
    node->setNodeMask(node->getNodeMask() | bit);
251
  else
252
    node->setNodeMask(node->getNodeMask() & ~bit);
253
}
254
255
1
MetaEnum* highlightStateEnum() {
256

1
  static MetaEnum hs;
257
1
  if (hs.type.size() == 0) {
258
1
    hs.type = "HighlightState";
259

1
    hs.names.push_back("None");
260
1
    hs.values.push_back(0);
261

1
    hs.names.push_back("1");
262
1
    hs.values.push_back(1);
263

1
    hs.names.push_back("2");
264
1
    hs.values.push_back(2);
265

1
    hs.names.push_back("3");
266
1
    hs.values.push_back(3);
267

1
    hs.names.push_back("4");
268
1
    hs.values.push_back(4);
269

1
    hs.names.push_back("5");
270
1
    hs.values.push_back(5);
271

1
    hs.names.push_back("6");
272
1
    hs.values.push_back(6);
273

1
    hs.names.push_back("7");
274
1
    hs.values.push_back(7);
275

1
    hs.names.push_back("8");
276
1
    hs.values.push_back(8);
277
  }
278
1
  return &hs;
279
}
280
}  // namespace
281
using ::osg::Matrix;
282
283
const float Node::TransparencyRenderingBinThreshold = 0.99f;
284
285
/* Declaration of private function members */
286
1
void Node::init() {
287
  /* Build local conformation
288
     <- wireframe_node_ptr_
289
     connected to the parent <- switch_node_ptr_                           <-
290
     auto_transform_ptr_ <- connection of children here
291
     <- normal_node_ptr_
292
  */
293
1
  scale_.value = osgVector3(1, 1, 1);
294
1
  scale_.min = 0.f;
295
1
  scale_.step = 0.1f;
296
1
  scale_.adaptiveDecimal = true;
297

1
  scale_.callback(boost::bind(&Node::updateTransform, this));
298
299
1
  M_.callback(scale_.callback());
300
301

1
  switch_node_ptr_ = new ::osg::Group;
302

1
  hl_switch_node_ptr_ = new ::osg::Group;
303

1
  transform_ptr_ = new ::osg::MatrixTransform;
304
1
  transform_ptr_->setName("positionInParentNode");
305
306
1
  switch_node_ptr_->setNodeMask(VisibilityBit | NodeBit | IntersectionBit);
307
1
  switch_node_ptr_->setName(id_name_);
308
1
  wireframe_modes_.resize(2);
309

1
  wireframe_modes_[FILL] = new ::osg::Group;
310
1
  wireframe_modes_[FILL]->setName("wireframe: FILL");
311

1
  wireframe_modes_[WIREFRAME] = new ::osg::Group;
312
1
  wireframe_modes_[WIREFRAME]->setName("wireframe: WIREFRAME");
313
314
  /* Building hierarchie */
315
1
  selected_wireframe_ = FILL;
316
1
  switch_node_ptr_->addChild(wireframe_modes_[FILL]);
317
1
  wireframe_modes_[FILL]->addChild(hl_switch_node_ptr_);
318
1
  wireframe_modes_[FILL]->setDataVariance(osg::Object::STATIC);
319
320
  // Setup highlight states
321
1
  highlight_nodes_.resize(9);
322
1
  selected_highlight_ = 0;
323
1
  highlight_enabled_ = true;
324
1
  highlight_nodes_[0] = transform_ptr_;
325
9
  for (unsigned int i = 1; i < 9; ++i) {
326

8
    highlight_nodes_[i] = setupHighlightState(i);
327
8
    highlight_nodes_[i]->addChild(transform_ptr_);
328
  }
329
  // setHighlightState(0);
330
1
  hl_switch_node_ptr_->addChild(highlight_nodes_[selected_highlight_]);
331
1
  hl_switch_node_ptr_->setName("highlight switch");
332
333

1
  wireframe_modes_[WIREFRAME]->setStateSet(getWireframeStateSet());
334
1
  wireframe_modes_[WIREFRAME]->setDataVariance(osg::Object::STATIC);
335
1
  geode_ptr_ = NULL;
336
1
  alpha_ = 1.;
337
338
1
  visibilityMode_ = VISIBILITY_ON;
339
1
  lightingMode_ = LIGHT_INFLUENCE_ON;
340
341

1
  addProperty(EnumProperty::create(
342
1
      "Highlight/State", highlightStateEnum(),
343

2
      EnumProperty::Getter_t(boost::bind(getNodeHighlightState, this)),
344

2
      EnumProperty::Setter_t(boost::bind(setNodeHighlightState, this, _1))));
345

1
  addProperty(BoolProperty::create("Highlight/Enable", this,
346
                                   &Node::getHighlightEnabled,
347
                                   &Node::setHighlightEnabled));
348

1
  addProperty(EnumProperty::create(
349
1
      "Visibility", visibilityModeEnum(),
350

2
      EnumProperty::Getter_t(boost::bind(getNodeVisibilityMode, this)),
351

2
      EnumProperty::Setter_t(boost::bind(setNodeVisibilityMode, this, _1))));
352

1
  addProperty(EnumProperty::create(
353
1
      "WireframeMode", wireFrameModeEnum(),
354

2
      EnumProperty::Getter_t(boost::bind(getNodeWireFrameMode, this)),
355

2
      EnumProperty::Setter_t(boost::bind(setNodeWireFrameMode, this, _1))));
356

1
  addProperty(EnumProperty::create(
357
1
      "LightingMode", lightingModeEnum(),
358

2
      EnumProperty::Getter_t(boost::bind(getNodeLightingMode, this)),
359

2
      EnumProperty::Setter_t(boost::bind(setNodeLightingMode, this, _1))));
360

1
  addProperty(BoolProperty::create(
361
      "Landmark",
362
2
      BoolProperty::getterFromMemberFunction(this, &Node::hasLandmark),
363

2
      BoolProperty::Setter_t(boost::bind(setNodeLandmark, this, _1))));
364

1
  addProperty(BoolProperty::create("Selectable", this, &Node::isSelectable,
365
                                   &Node::setSelectable));
366

1
  addProperty(StringProperty::createRO("Name", this, &Node::getID));
367

1
  addProperty(Vector4Property::createWO("Color", this, &Node::setColor));
368
369
  RangedFloatProperty::Ptr_t alphaProp = RangedFloatProperty::create(
370

3
      "Alpha", this, &Node::getAlpha, &Node::setAlpha);
371
1
  alphaProp->setRange(0.f, 1.f, 0.1f);
372
1
  addProperty(alphaProp);
373
374
1
  addProperty(&scale_);
375
1
  addProperty(&M_);
376
1
}
377
378
1
Node::Node(const std::string& name)
379



1
    : id_name_(name), dirty_(true), scale_("Scale"), M_("Transform") {
380
1
  init();
381
1
}
382
383
Node::Node(const Node& other)
384
    : id_name_(other.getID()), dirty_(true), scale_("Scale"), M_("Transform") {
385
  init();
386
}
387
388
void Node::setSelectable(bool selectable) {
389
  setFlag(transform_ptr_.get(), IntersectionBit, selectable);
390
}
391
392
5
void Node::updateTransform() {
393
5
  osg::Matrixf M;
394
5
  M.setRotate(M_.value.quat);
395
5
  M.setTrans(M_.value.position);
396
397



5
  transform_ptr_->setMatrix(::osg::Matrix::scale(scale_.value) * Ms_ * M);
398
5
  dirty_ = true;
399
5
}
400
401
2
void Node::setStaticTransform(const osgVector3& position, const osgQuat& quat) {
402
2
  Ms_.setRotate(quat);
403
2
  Ms_.setTrans(position);
404
405
2
  updateTransform();
406
2
}
407
408
2
osgQuat Node::getStaticRotation() const {
409
2
  osgQuat q, so;
410
2
  osgVector3 t, s;
411
2
  Ms_.decompose(t, q, s, so);
412
4
  return q;
413
}
414
415
2
osgVector3 Node::getStaticPosition() const {
416
2
  osgQuat q, so;
417
2
  osgVector3 t, s;
418
2
  Ms_.decompose(t, q, s, so);
419
2
  return t;
420
}
421
422
void Node::setVisibilityMode(const VisibilityMode& mode) {
423
  if (visibilityMode_ == mode) return;
424
  visibilityMode_ = mode;
425
  switch (mode) {
426
    case VISIBILITY_ON:
427
      setFlag(transform_ptr_.get(), VisibilityBit, true);
428
      transform_ptr_->setStateSet(getVisibleStateSet(lightingMode_));
429
      break;
430
    case VISIBILITY_OFF:
431
      setFlag(transform_ptr_.get(), VisibilityBit, false);
432
      transform_ptr_->setStateSet(getVisibleStateSet(lightingMode_));
433
      break;
434
    case ALWAYS_ON_TOP:
435
      setFlag(transform_ptr_.get(), VisibilityBit, true);
436
      transform_ptr_->setStateSet(getAlwaysOnTopStateSet(lightingMode_));
437
      break;
438
439
    default:
440
      ASSERT(false, "mode is not well defined");
441
      break;
442
  }
443
  dirty_ = true;
444
}
445
446
void Node::setLightingMode(const LightingMode& mode) {
447
  if (mode == lightingMode_) return;
448
  lightingMode_ = mode;
449
  switch (visibilityMode_) {
450
    case VISIBILITY_ON:
451
    case VISIBILITY_OFF:
452
      transform_ptr_->setStateSet(getVisibleStateSet(lightingMode_));
453
      break;
454
    case ALWAYS_ON_TOP:
455
      transform_ptr_->setStateSet(getAlwaysOnTopStateSet(lightingMode_));
456
      break;
457
    default:
458
      ASSERT(false, "mode is not well defined");
459
      break;
460
  }
461
  dirty_ = true;
462
}
463
464
LightingMode Node::getLightingMode() const { return lightingMode_; }
465
466
void Node::setWireFrameMode(const WireFrameMode& mode) {
467
  if (mode == selected_wireframe_) return;
468
  bool fillSelected = (selected_wireframe_ == FILL) ||
469
                      (selected_wireframe_ == FILL_AND_WIREFRAME);
470
  bool wireSelected = (selected_wireframe_ == WIREFRAME) ||
471
                      (selected_wireframe_ == FILL_AND_WIREFRAME);
472
  // 0: keep as it is
473
  // 1: select
474
  // 2: deselect
475
  int selectFill = 0, selectWire = 0;
476
  switch (mode) {
477
    case FILL:
478
      if (wireSelected) selectWire = 2;
479
      if (!fillSelected) selectFill = 1;
480
      break;
481
    case WIREFRAME:
482
      if (!wireSelected) selectWire = 1;
483
      if (fillSelected) selectFill = 2;
484
      break;
485
    case FILL_AND_WIREFRAME:
486
      if (!wireSelected) selectWire = 1;
487
      if (!fillSelected) selectFill = 1;
488
      break;
489
    default:
490
      ASSERT(false, "WireFrameMode set with bad option");
491
      break;
492
  }
493
  switch (selectFill) {
494
    case 0:
495
      break;
496
    case 1:
497
      wireframe_modes_[FILL]->addChild(hl_switch_node_ptr_);
498
      switch_node_ptr_->addChild(wireframe_modes_[FILL]);
499
      break;
500
    case 2:
501
      wireframe_modes_[FILL]->removeChild(hl_switch_node_ptr_);
502
      switch_node_ptr_->removeChild(wireframe_modes_[FILL]);
503
      break;
504
    default:
505
      assert(false && "Wrong action");
506
  };
507
  switch (selectWire) {
508
    case 0:
509
      break;
510
    case 1:
511
      wireframe_modes_[WIREFRAME]->addChild(hl_switch_node_ptr_);
512
      switch_node_ptr_->addChild(wireframe_modes_[WIREFRAME]);
513
      break;
514
    case 2:
515
      wireframe_modes_[WIREFRAME]->removeChild(hl_switch_node_ptr_);
516
      switch_node_ptr_->removeChild(wireframe_modes_[WIREFRAME]);
517
      break;
518
    default:
519
      assert(false && "Wrong action");
520
  };
521
  selected_wireframe_ = mode;
522
  dirty_ = true;
523
}
524
525
void Node::addLandmark(const float& size) {
526
  ::osg::GeometryRefPtr geom_ptr = new ::osg::Geometry();
527
528
  /* Define points of the beam */
529
  ::osg::Vec3ArrayRefPtr points_ptr = new ::osg::Vec3Array(6);
530
  points_ptr->at(0) = osgVector3(0., 0., 0.);
531
  points_ptr->at(1) = osgVector3(size, 0., 0.);
532
  points_ptr->at(2) = osgVector3(0., 0., 0.);
533
  points_ptr->at(3) = osgVector3(0., size, 0.);
534
  points_ptr->at(4) = osgVector3(0., 0., 0.);
535
  points_ptr->at(5) = osgVector3(0., 0., size);
536
537
  /* Define the color */
538
  ::osg::Vec4ArrayRefPtr color_ptr = new ::osg::Vec4Array(3);
539
  color_ptr->at(0) = osgVector4(1., 0., 0., 1.);
540
  color_ptr->at(1) = osgVector4(0., 1., 0., 1.);
541
  color_ptr->at(2) = osgVector4(0., 0., 1., 1.);
542
543
  geom_ptr->setVertexArray(points_ptr.get());
544
  geom_ptr->setColorArray(color_ptr.get());
545
  geom_ptr->setColorBinding(::osg::Geometry::BIND_PER_PRIMITIVE_SET);
546
  geom_ptr->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 0, 2));
547
  geom_ptr->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 2, 2));
548
  geom_ptr->addPrimitiveSet(new osg::DrawArrays(GL_LINES, 4, 2));
549
550
  transform_ptr_->removeChild(landmark_geode_ptr_);
551
  landmark_geode_ptr_ = new osg::Geode();
552
  landmark_geode_ptr_->addDrawable(geom_ptr);
553
554
  // set Landmark as ALWAYS ON TOP
555
  setFlag(landmark_geode_ptr_.get(), VisibilityBit, true);
556
  landmark_geode_ptr_->setStateSet(getAlwaysOnTopStateSet(LIGHT_INFLUENCE_OFF));
557
558
  transform_ptr_->addChild(landmark_geode_ptr_);
559
  dirty_ = true;
560
}
561
562
bool Node::hasLandmark() const { return landmark_geode_ptr_; }
563
564
void Node::deleteLandmark() {
565
  if (landmark_geode_ptr_) {
566
    transform_ptr_->removeChild(landmark_geode_ptr_);
567
    landmark_geode_ptr_.release();
568
    dirty_ = true;
569
  }
570
}
571
572
8
::osg::Group* Node::setupHighlightState(unsigned int state) {
573
16
  osg::StateSetRefPtr ss;
574


8
  switch (state) {
575
1
    case 1:  /// collision
576

1
      ss = getHighlightStateSet<1>();
577
1
      break;
578
1
    case 2:  /// selection
579

1
      ss = getHighlightStateSet<2>();
580
1
      break;
581
1
    case 3:  /// selection
582

1
      ss = getHighlightStateSet<3>();
583
1
      break;
584
1
    case 4:  /// selection
585

1
      ss = getHighlightStateSet<4>();
586
1
      break;
587
1
    case 5:  /// selection
588

1
      ss = getHighlightStateSet<5>();
589
1
      break;
590
1
    case 6:  /// selection
591

1
      ss = getHighlightStateSet<6>();
592
1
      break;
593
1
    case 7:  /// Selection through osgFX::Outline
594
    {
595

1
      osgFX::Outline* outline = new osgFX::Outline;
596
597
1
      outline->setWidth(8);
598
1
      outline->setColor(osg::Vec4(1, 1, 0, 1));
599
1
      outline->setDataVariance(osg::Object::STATIC);
600
1
      return outline;
601
    } break;
602
1
    case 8:  /// Selection through osgFX::Outline
603
    {
604

1
      osgFX::Scribe* scribe = new osgFX::Scribe;
605
606
1
      scribe->setWireframeLineWidth(1);
607
1
      scribe->setWireframeColor(osg::Vec4(1, 1, 0, 1));
608
1
      scribe->setDataVariance(osg::Object::STATIC);
609
1
      return scribe;
610
    } break;
611
    case 0:
612
    default:
613
      break;
614
  }
615

6
  osg::Group* node = new ::osg::Group;
616
6
  node->setStateSet(ss);
617
6
  node->setDataVariance(osg::Object::STATIC);
618
6
  return node;
619
}
620
621
void Node::setHighlightState(unsigned int state) {
622
  if (!highlight_enabled_) return;
623
  if (state != selected_highlight_ && state < highlight_nodes_.size()) {
624
    hl_switch_node_ptr_->replaceChild(highlight_nodes_[selected_highlight_],
625
                                      highlight_nodes_[state]);
626
    // Update the child
627
    selected_highlight_ = state;
628
    dirty_ = true;
629
  }
630
}
631
632
void Node::setAlpha(const float& alpha) {
633
  if (geode_ptr_.get() == NULL) {
634
    log() << "You must initialize a Geode on " << id_name_ << " to use Alpha"
635
          << std::endl;
636
    return;
637
  }
638
  osg::StateSet* ss = geode_ptr_.get()->getStateSet();
639
  if (ss) {
640
    alpha_ = alpha;
641
    osg::Material* mat;
642
    if (ss->getAttribute(osg::StateAttribute::MATERIAL))
643
      mat = dynamic_cast<osg::Material*>(
644
          ss->getAttribute(osg::StateAttribute::MATERIAL));
645
    else {
646
      mat = new osg::Material;
647
      ss->setAttribute(mat, osg::StateAttribute::OFF);
648
    }
649
    mat->setAlpha(osg::Material::FRONT_AND_BACK, alpha);
650
    setTransparentRenderingBin(alpha_ < TransparencyRenderingBinThreshold);
651
    dirty_ = true;
652
  }
653
}
654
655
float Node::getAlpha() const { return alpha_; }
656
657
void Node::setTransparency(const float& transparency) {
658
  setAlpha(1.f - transparency);
659
}
660
661
float Node::getTransparency() const { return 1.f - getAlpha(); }
662
663
1
void Node::setTransparentRenderingBin(bool transparent, osg::StateSet* ss) {
664
1
  if (ss == NULL) {
665
1
    if (geode_ptr_.get() == NULL) {
666
      log() << "You must initialize a Geode on " << id_name_ << " to use Alpha"
667
            << std::endl;
668
      return;
669
    }
670
1
    ss = geode_ptr_.get()->getStateSet();
671
1
    if (ss == NULL) return;
672
  }
673
  bool isTransparent =
674
1
      (ss->getRenderingHint() == osg::StateSet::TRANSPARENT_BIN);
675
1
  if (transparent == isTransparent) return;
676
  if (transparent)
677
    ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
678
  else
679
    ss->setRenderingHint(osg::StateSet::DEFAULT_BIN);
680
  dirty_ = true;
681
}
682
683
2
Node::~Node() {
684
  /* Proper deletion */
685
  /* deleting the top most node (switch_node_ptr_) will delete everything else.
686
   * Loop over the parents of switch_node_ptr_ and remove references to it.
687
   */
688
  typedef ::osg::Node::ParentList PL_t;
689
4
  PL_t parents = switch_node_ptr_->getParents();
690
2
  for (PL_t::const_iterator _p = parents.begin(); _p != parents.end(); ++_p)
691
    (*_p)->removeChild(switch_node_ptr_);
692
}
693
694
2
const Configuration& Node::getGlobalTransform() const { return M_.value; }
695
696
void Node::traverse(NodeVisitor& /*visitor*/) {}
697
698
osg::ref_ptr<osg::Node> Node::getOsgNode() const { return geode_ptr_.get(); }
699
700
/* End of declaration of public function members */
701
702
} /* namespace viewer */
703
704
} /* namespace gepetto */