Developer Documentation
SplatCloudObject.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 //================================================================
51 //
52 // SplatCloudObject
53 //
54 //================================================================
55 
56 
57 #define SPLATCLOUDOBJECT_C
58 
59 
60 //== INCLUDES ====================================================
61 
62 
63 #include "SplatCloud.hh"
66 
67 
68 //== DEFINES =====================================================
69 
70 
71 //#define REPORT_UPDATE_TYPE
72 
73 
74 //== IMPLEMENTATION ==============================================
75 
76 
84 BaseObjectData ( ),
85 backfaceCullingEnabled_( false ),
86 pointsizeScale_ ( 1.0f ),
87 shaderNode_ ( 0 ),
88 splatCloudNode_ ( 0 )
89 {
90  // allocate memory for splat cloud
91  splatCloud_ = new SplatCloud;
92  if( !splatCloud_ )
93  {
94  std::cerr << "SplatCloudObject::SplatCloudObject() : Out of memory." << std::endl;
95  }
96 
98  setTypeIcon( DATA_SPLATCLOUD, "SplatCloudType.png" );
99  init();
100 }
101 
102 
103 //----------------------------------------------------------------
104 
105 
110 {
111  init( _object.splatCloud_ );
112  setName( name() );
113 }
114 
115 
116 //----------------------------------------------------------------
117 
118 
123 {
124  // Delete the data attached to this object ( this will remove all perObject data)
125  // Not the best way to do it but it will work.
126  // This is only necessary if people use references to the SplatCloud below and
127  // they do something with the SplatCloud in the destructor of their
128  // perObjectData.
129  deleteData();
130 
131  // No need to delete the scenegraph Nodes as this will be managed by baseplugin
132  shaderNode_ = 0;
133  splatCloudNode_ = 0;
134 
135  // free memory of splat cloud
136  delete splatCloud_;
137  splatCloud_ = 0;
138 }
139 
140 
141 //----------------------------------------------------------------
142 
143 
148 {
150 
151  shaderNode_ = 0;
152  splatCloudNode_ = 0;
153 
154  init();
155 }
156 
157 
158 //----------------------------------------------------------------
159 
160 
165 {
166  SplatCloudObject *object = new SplatCloudObject( *this );
167  return dynamic_cast<BaseObject *>( object );
168 }
169 
170 
171 //----------------------------------------------------------------
172 
173 
178 {
179  // standard shader filenames
180  static const char SPLATS_VERTEXSHADER_FILENAME[] = "SplatCloud_Splats/Vertex.glsl";
181  static const char SPLATS_FRAGMENTSHADER_FILENAME[] = "SplatCloud_Splats/Fragment.glsl";
182  static const char DOTS_VERTEXSHADER_FILENAME[] = "SplatCloud_Dots/Vertex.glsl";
183  static const char DOTS_FRAGMENTSHADER_FILENAME[] = "SplatCloud_Dots/Fragment.glsl";
184  static const char POINTS_VERTEXSHADER_FILENAME[] = "SplatCloud_Points/Vertex.glsl";
185  static const char POINTS_FRAGMENTSHADER_FILENAME[] = "SplatCloud_Points/Fragment.glsl";
186 
187  // picking shader filenames
188  static const char SPLATS_PICK_VERTEXSHADER_FILENAME[] = "SplatCloud_Splats/PickVertex.glsl";
189  static const char SPLATS_PICK_FRAGMENTSHADER_FILENAME[] = "SplatCloud_Splats/Fragment.glsl";
190  static const char DOTS_PICK_VERTEXSHADER_FILENAME[] = "SplatCloud_Dots/PickVertex.glsl";
191  static const char DOTS_PICK_FRAGMENTSHADER_FILENAME[] = "SplatCloud_Dots/Fragment.glsl";
192  static const char POINTS_PICK_VERTEXSHADER_FILENAME[] = "SplatCloud_Points/PickVertex.glsl";
193  static const char POINTS_PICK_FRAGMENTSHADER_FILENAME[] = "SplatCloud_Points/Fragment.glsl";
194 
195  // get drawmodes
199 
200  // if drawmodes don't exist something went wrong
201  if( splatsDrawMode == ACG::SceneGraph::DrawModes::NONE ||
202  dotsDrawMode == ACG::SceneGraph::DrawModes::NONE ||
203  pointsDrawMode == ACG::SceneGraph::DrawModes::NONE )
204  {
205  std::cerr << "Shader DrawModes for SplatCloud not existent!" << std::endl;
206  return;
207  }
208 
209  // get shader directory
210  QString shaderDir = OpenFlipper::Options::shaderDirStr() + OpenFlipper::Options::dirSeparator();
211  std::string shaderDirectory = std::string( shaderDir.toUtf8() );
212 
213  // set shader directory
214  shaderNode_->setShaderDir( shaderDirectory );
215 
216  // load shaders
217 
218  if( QFile( shaderDir + SPLATS_VERTEXSHADER_FILENAME ).exists() &&
219  QFile( shaderDir + SPLATS_PICK_VERTEXSHADER_FILENAME ).exists() &&
220  QFile( shaderDir + SPLATS_FRAGMENTSHADER_FILENAME ).exists() &&
221  QFile( shaderDir + SPLATS_PICK_FRAGMENTSHADER_FILENAME ).exists() )
222  {
223  shaderNode_->setShader( splatsDrawMode,
224  SPLATS_VERTEXSHADER_FILENAME, SPLATS_FRAGMENTSHADER_FILENAME,
225  SPLATS_PICK_VERTEXSHADER_FILENAME, SPLATS_PICK_FRAGMENTSHADER_FILENAME );
226  }
227  else
228  {
229  std::cerr << "Shader Files for SplatCloud/Splats not found!" << std::endl;
230  }
231 
232  if( QFile( shaderDir + DOTS_VERTEXSHADER_FILENAME ).exists() &&
233  QFile( shaderDir + DOTS_PICK_VERTEXSHADER_FILENAME ).exists() &&
234  QFile( shaderDir + DOTS_FRAGMENTSHADER_FILENAME ).exists() &&
235  QFile( shaderDir + DOTS_PICK_FRAGMENTSHADER_FILENAME ).exists() )
236  {
237  shaderNode_->setShader( dotsDrawMode,
238  DOTS_VERTEXSHADER_FILENAME, DOTS_FRAGMENTSHADER_FILENAME,
239  DOTS_PICK_VERTEXSHADER_FILENAME, DOTS_PICK_FRAGMENTSHADER_FILENAME );
240  }
241  else
242  {
243  std::cerr << "Shader Files for SplatCloud/Dots not found!" << std::endl;
244  }
245 
246  if( QFile( shaderDir + POINTS_VERTEXSHADER_FILENAME ).exists() &&
247  QFile( shaderDir + POINTS_PICK_VERTEXSHADER_FILENAME ).exists() &&
248  QFile( shaderDir + POINTS_FRAGMENTSHADER_FILENAME ).exists() &&
249  QFile( shaderDir + POINTS_PICK_FRAGMENTSHADER_FILENAME ).exists() )
250  {
251  shaderNode_->setShader( pointsDrawMode,
252  POINTS_VERTEXSHADER_FILENAME, POINTS_FRAGMENTSHADER_FILENAME,
253  POINTS_PICK_VERTEXSHADER_FILENAME, POINTS_PICK_FRAGMENTSHADER_FILENAME );
254  }
255  else
256  {
257  std::cerr << "Shader Files for SplatCloud/Points not found!" << std::endl;
258  }
259 }
260 
261 
262 //----------------------------------------------------------------
263 
264 
269 {
270  // get drawmodes
274 
275  // if drawmodes don't exist something went wrong
276  if( splatsDrawMode == ACG::SceneGraph::DrawModes::NONE ||
277  dotsDrawMode == ACG::SceneGraph::DrawModes::NONE ||
278  pointsDrawMode == ACG::SceneGraph::DrawModes::NONE )
279  {
280  std::cerr << "Shader DrawModes for SplatCloud not existent!" << std::endl;
281  return;
282  }
283 
284  // get standard and picking shaders
285  GLSL::PtrProgram splatsShader = shaderNode_->getShader( splatsDrawMode, false );
286  GLSL::PtrProgram splatsPickShader = shaderNode_->getShader( splatsDrawMode, true );
287  GLSL::PtrProgram dotsShader = shaderNode_->getShader( dotsDrawMode, false );
288  GLSL::PtrProgram dotsPickShader = shaderNode_->getShader( dotsDrawMode, true );
289  GLSL::PtrProgram pointsShader = shaderNode_->getShader( pointsDrawMode, false );
290  GLSL::PtrProgram pointsPickShader = shaderNode_->getShader( pointsDrawMode, true );
291 
292  // update backface-culling uniform of shaders
293 
294  backfaceCullingEnabled_ = _enable;
295  GLint backfaceCulling = (GLint) _enable;
296 
297  if( splatsShader )
298  {
299  splatsShader->use();
300  splatsShader->setUniform( "backfaceCulling", backfaceCulling );
301  splatsShader->disable();
302  }
303 
304  if( splatsPickShader )
305  {
306  splatsPickShader->use();
307  splatsPickShader->setUniform( "backfaceCulling", backfaceCulling );
308  splatsPickShader->disable();
309  }
310 
311  if( dotsShader )
312  {
313  dotsShader->use();
314  dotsShader->setUniform( "backfaceCulling", backfaceCulling );
315  dotsShader->disable();
316  }
317 
318  if( dotsPickShader )
319  {
320  dotsPickShader->use();
321  dotsPickShader->setUniform( "backfaceCulling", backfaceCulling );
322  dotsPickShader->disable();
323  }
324 
325  if( pointsShader )
326  {
327  pointsShader->use();
328  pointsShader->setUniform( "backfaceCulling", backfaceCulling );
329  pointsShader->disable();
330  }
331 
332  if( pointsPickShader )
333  {
334  pointsPickShader->use();
335  pointsPickShader->setUniform( "backfaceCulling", backfaceCulling );
336  pointsPickShader->disable();
337  }
338 }
339 
340 
341 //----------------------------------------------------------------
342 
343 
348 {
349  // get drawmodes
352 
353  // if drawmodes don't exist something went wrong
354  if( splatsDrawMode == ACG::SceneGraph::DrawModes::NONE ||
355  dotsDrawMode == ACG::SceneGraph::DrawModes::NONE )
356  {
357  std::cerr << "Shader DrawModes for SplatCloud not existent!" << std::endl;
358  return;
359  }
360 
361  // get standard and picking shaders
362  GLSL::PtrProgram splatsShader = shaderNode_->getShader( splatsDrawMode, false );
363  GLSL::PtrProgram splatsPickShader = shaderNode_->getShader( splatsDrawMode, true );
364  GLSL::PtrProgram dotsShader = shaderNode_->getShader( dotsDrawMode, false );
365  GLSL::PtrProgram dotsPickShader = shaderNode_->getShader( dotsDrawMode, true );
366 
367  // update pointsize-scale uniform of shaders
368 
369  pointsizeScale_ = _scale;
370  GLfloat pointsizeScale = (GLfloat) _scale;
371 
372  if( splatsShader )
373  {
374  splatsShader->use();
375  splatsShader->setUniform( "pointsizeScale", pointsizeScale );
376  splatsShader->disable();
377  }
378 
379  if( splatsPickShader )
380  {
381  splatsPickShader->use();
382  splatsPickShader->setUniform( "pointsizeScale", pointsizeScale );
383  splatsPickShader->disable();
384  }
385 
386  if( dotsShader )
387  {
388  dotsShader->use();
389  dotsShader->setUniform( "pointsizeScale", pointsizeScale );
390  dotsShader->disable();
391  }
392 
393  if( dotsPickShader )
394  {
395  dotsPickShader->use();
396  dotsPickShader->setUniform( "pointsizeScale", pointsizeScale );
397  dotsPickShader->disable();
398  }
399 }
400 
401 
402 //----------------------------------------------------------------
403 
404 
407 void SplatCloudObject::init( const SplatCloud *_splatCloud )
408 {
409  if( materialNode() == NULL )
410  std::cerr << "Error when creating SplatCloud Object! materialNode is NULL!" << std::endl;
411 
412  // if _splatCloud is *not* 0, copy it's contents
413  if( _splatCloud )
414  {
415  delete splatCloud_;
416 
417  splatCloud_ = new SplatCloud( *_splatCloud );
418  if( !splatCloud_ )
419  {
420  std::cerr << "SplatCloudObject::init() : Out of memory." << std::endl;
421  }
422  }
423 
424  // if something went wrong during initialization, abort
425  if( !splatCloud_ )
426  {
427  shaderNode_ = 0;
428  splatCloudNode_ = 0;
429  return;
430  }
431 
432  // create new scenegraph nodes
433  shaderNode_ = new ShaderNode ( materialNode(), "NEW ShaderNode for" );
434  splatCloudNode_ = new SplatCloudNode( *splatCloud_, shaderNode_, "NEW SplatCloudNode" );
435 
436  // load shaders
437  reloadShaders();
438 }
439 
440 
441 //----------------------------------------------------------------
442 
443 
448 {
449  if( _type == UPDATE_ALL )
450  {
451 # ifdef REPORT_UPDATE_TYPE
452  std::cout << "SplatCloudObject::update() : UPDATE_ALL" << std::endl;
453  std::cout << std::endl;
454 # endif
455 
456  if( splatCloudNode_ )
457  splatCloudNode_->modifiedAll();
458  return;
459  }
460 
461  if( _type.contains( UPDATE_GEOMETRY ) )
462  {
463 # ifdef REPORT_UPDATE_TYPE
464  std::cout << "SplatCloudObject::update() : UPDATE_GEOMETRY" << std::endl;
465 # endif
466 
467  if( splatCloudNode_ )
468  splatCloudNode_->modifiedPositions();
469  }
470 
471  if( _type.contains( UPDATE_COLOR ) )
472  {
473 # ifdef REPORT_UPDATE_TYPE
474  std::cout << "SplatCloudObject::update() : UPDATE_COLOR" << std::endl;
475 # endif
476 
477  if( splatCloudNode_ )
478  splatCloudNode_->modifiedColors();
479  }
480 
481  if( _type.contains( updateType("Normals") ) )
482  {
483 # ifdef REPORT_UPDATE_TYPE
484  std::cout << "SplatCloudObject::update() : UPDATE_Normals" << std::endl;
485 # endif
486 
487  if( splatCloudNode_ )
488  splatCloudNode_->modifiedNormals();
489  }
490 
491  if( _type.contains( updateType("Pointsizes") ) )
492  {
493 # ifdef REPORT_UPDATE_TYPE
494  std::cout << "SplatCloudObject::update() : UPDATE_Pointsizes" << std::endl;
495 # endif
496 
497  if( splatCloudNode_ )
498  splatCloudNode_->modifiedPointsizes();
499  }
500 
501  if( _type.contains( updateType("Indices") ) )
502  {
503 # ifdef REPORT_UPDATE_TYPE
504  std::cout << "SplatCloudObject::update() : UPDATE_Indices" << std::endl;
505 # endif
506  }
507 
508  if( _type.contains( UPDATE_SELECTION ) )
509  {
510 # ifdef REPORT_UPDATE_TYPE
511  std::cout << "SplatCloudObject::update() : UPDATE_SELECTION" << std::endl;
512 # endif
513 
514  if( splatCloudNode_ )
515  splatCloudNode_->modifiedSelections();
516  }
517 
518 # ifdef REPORT_UPDATE_TYPE
519  std::cout << std::endl;
520 # endif
521 }
522 
523 
524 //----------------------------------------------------------------
525 // Name/Path Handling
526 //----------------------------------------------------------------
527 
528 
532 void SplatCloudObject::setName( QString _name )
533 {
534  BaseObjectData::setName( _name );
535 
536  std::string nodename;
537 
538  nodename = std::string( "ShaderNode for SplatCloud " + _name.toUtf8() );
539  shaderNode_->name( nodename );
540 
541  nodename = std::string( "SplatCloudNode for SplatCloud " + _name.toUtf8() );
542  splatCloudNode_->name( nodename );
543 }
544 
545 
546 //----------------------------------------------------------------
547 // Object information
548 //----------------------------------------------------------------
549 
550 
557 {
558  QString output;
559 
560  output += "========================================================================\n";
561  output += BaseObjectData::getObjectinfo();
562 
563  if( dataType( DATA_SPLATCLOUD ) )
564  {
565  output += "Object Contains SplatCloud: ";
566 
567  if( splatCloud_ )
568  {
569  output += " #Splats: " + QString::number( splatCloud_->numSplats() );
570 
571  output += "; Splat-Properties: ";
572  if( splatCloud_->splatProperties().empty() )
573  {
574  output += "-none-";
575  }
576  else
577  {
578  SplatCloud::SplatPropertyMap::const_iterator splatPropertyIter = splatCloud_->splatProperties().begin();
579  while( true )
580  {
581  output += splatPropertyIter->first.c_str();
582 
583  if( ++splatPropertyIter == splatCloud_->splatProperties().end() )
584  break;
585 
586  output += ", ";
587  }
588  }
589 
590  output += "; Cloud-Properties: ";
591  if( splatCloud_->cloudProperties().empty() )
592  {
593  output += "-none-";
594  }
595  else
596  {
597  SplatCloud::CloudPropertyMap::const_iterator cloudPropertyIter = splatCloud_->cloudProperties().begin();
598  while( true )
599  {
600  output += cloudPropertyIter->first.c_str();
601 
602  if( ++cloudPropertyIter == splatCloud_->cloudProperties().end() )
603  break;
604 
605  output += ", ";
606  }
607  }
608  }
609 
610  output += "\n";
611  }
612 
613  output += "========================================================================\n";
614  return output;
615 }
616 
617 
618 //----------------------------------------------------------------
619 // Picking
620 //----------------------------------------------------------------
621 
622 
629 bool SplatCloudObject::picked( uint _node_idx )
630 {
631  return ( _node_idx == splatCloudNode_->id() );
632 }
633 
634 
635 //----------------------------------------------------------------
636 
637 
639 {
640  splatCloudNode_->enablePicking( _enable );
641  shaderNode_->enablePicking( _enable );
642 }
643 
644 
645 //----------------------------------------------------------------
646 
647 
649 {
651 }
GLSL::PtrProgram getShader(DrawModes::DrawMode _drawmode, bool _pick=false)
Get the shader for the given drawMode.
Definition: ShaderNode.cc:228
const DrawMode & getDrawMode(const std::string &_name)
Get a custom DrawMode.
Definition: DrawModes.cc:813
void setDataType(DataType _type)
Definition: BaseObject.cc:244
virtual void cleanup()
void enablePicking(bool _enable)
Enable or disable picking for this Object.
UpdateType updateType(QString _name)
Get the id of a type with given name.
Definition: UpdateType.cc:259
ACG::SceneGraph::SplatCloudNode SplatCloudNode
Simple Name for SplatCloudNode.
ACG::SceneGraph::ShaderNode ShaderNode
Simple Name for ShaderNode.
virtual ~SplatCloudObject()
Destructor.
const SplatPropertyMap & splatProperties() const
Get all splat-properties.
Definition: SplatCloud.hh:453
SplatCloudNode * splatCloudNode_
Get Shader&#39;s scenegraph Node.
#define DATA_SPLATCLOUD
Definition: SplatCloud.hh:65
ShaderNode * shaderNode_
Get Shader&#39;s scenegraph Node.
BaseObject * copy()
void use()
Enables the program object for using.
Definition: GLSLShader.cc:351
Update type class.
Definition: UpdateType.hh:70
MaterialNode * materialNode()
get a pointer to the materialnode
void setPointsizeScale(float _scale)
Set the scaling factor for pointsizes for all Shaders.
const UpdateType UPDATE_COLOR(UpdateTypeSet(1)<< 10)
Colors have changed.
bool contains(const UpdateType &_type) const
Check if this update contains the given UpdateType.
Definition: UpdateType.cc:111
void setShaderDir(std::string _shaderDir)
Sets the shader dir.
Definition: ShaderNode.cc:398
virtual void setName(QString _name)
path to the file from which the object is loaded ( defaults to "." )
virtual void init(const SplatCloud *_splatCloud=0)
Initialise current Object, including all related Nodes.
const CloudPropertyMap & cloudProperties() const
Get all cloud-properties.
Definition: SplatCloud.hh:463
void deleteData()
Delete all data attached to this object ( calls delete on each object )
Definition: BaseObject.cc:823
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:391
unsigned int numSplats() const
Get the number of splats.
Definition: SplatCloud.hh:185
std::string name() const
Returns: name of node (needs not be unique)
Definition: MeshNode2T.cc:446
DLLEXPORT void setTypeIcon(DataType _id, QString _icon)
Set an Icon for a given DataType.
Definition: Types.cc:234
DrawMode NONE
not a valid draw mode
Definition: DrawModes.cc:77
void setName(QString _name)
Set the name of the Object.
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:741
const UpdateType UPDATE_SELECTION(UpdateTypeSet(1)<< 4)
Selection updated.
virtual void cleanup()
Reset current Object, including all related Nodes.
bool pickingEnabled()
Check if picking is enabled for this Object.
virtual QString getObjectinfo()
Get all Info for the Object as a string.
Definition: BaseObject.cc:255
void reloadShaders()
Reload standard and picking Shaders from file.
void enableBackfaceCulling(bool _enable)
Enable or disable backface culling for all Shaders.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
SplatCloud * splatCloud_
Get SplatCloud.
void setShader(DrawModes::DrawMode _drawmode, std::string _vertexShader, std::string _fragmentShader, std::string _pickVertexShader="", std::string _pickFragmentShader="")
Definition: ShaderNode.cc:297
void disable()
Resets to standard rendering pipeline.
Definition: GLSLShader.cc:361
DataType dataType() const
Definition: BaseObject.cc:240
GLSL program class.
Definition: GLSLShader.hh:217
void update(UpdateType _type=UPDATE_ALL)
Called by the core if the object has to be updated.
QString getObjectinfo()
Get all Info for the Object as a string.
SplatCloudObject()
Constructor.
bool picked(uint _node_idx)
Detect if the node has been picked.