Developer Documentation
FilePTS.cc
1 //================================================================
2 //
3 /*===========================================================================*\
4 * *
5  * OpenFlipper *
6  * Copyright (c) 2001-2015, RWTH-Aachen University *
7  * Department of Computer Graphics and Multimedia *
8  * All rights reserved. *
9  * www.openflipper.org *
10  * *
11  *---------------------------------------------------------------------------*
12  * This file is part of OpenFlipper. *
13  *---------------------------------------------------------------------------*
14  * *
15  * Redistribution and use in source and binary forms, with or without *
16  * modification, are permitted provided that the following conditions *
17  * are met: *
18  * *
19  * 1. Redistributions of source code must retain the above copyright notice, *
20  * this list of conditions and the following disclaimer. *
21  * *
22  * 2. Redistributions in binary form must reproduce the above copyright *
23  * notice, this list of conditions and the following disclaimer in the *
24  * documentation and/or other materials provided with the distribution. *
25  * *
26  * 3. Neither the name of the copyright holder nor the names of its *
27  * contributors may be used to endorse or promote products derived from *
28  * this software without specific prior written permission. *
29  * *
30  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
31  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
32  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
33  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
34  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
35  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
36  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
37  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
38  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
39  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
40  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
41  * *
42  \*===========================================================================*/
43 
44 
45 //== INCLUDES ====================================================
46 
47 
48 #include "FilePTS.hh"
49 
50 #include "Snappy/snappy.h"
51 
52 
53 
56 
57 
58 //== CONSTANTS ===================================================
59 
60 
61 // constants of color range drop down box
62 static const int COLORRANGE_0_1 = 0;
63 //static const int COLORRANGE_0_255 = 1;
64 
65 
66 //== IMPLEMENTATION ==============================================
67 
68 template <typename MeshT>
69 class AdaptorMesh : public AdaptorBase {
70 public:
71  AdaptorMesh(MeshT& _mesh, DataType _type) : mesh_(_mesh),currentPoint_(0),type_(_type) {}
72 
73  virtual ~AdaptorMesh() {
74 
75  }
76 
77  void clear() override {
78  mesh_.clear();
79  }
80 
81  void add_point(ACG::Vec3d _point) override {
82  currentPoint_ = mesh_.add_vertex(_point);
83  }
84 
85  void setNormal(ACG::Vec3d _normal) override{
86  mesh_.set_normal( currentPoint_,_normal );
87  }
88 
89  void setColor(ACG::Vec4f _color) override{
90  mesh_.set_color( currentPoint_,_color );
91  }
92 
93  void setColor(ACG::Vec3uc _color) override{
94  mesh_.set_color( currentPoint_, OpenMesh::color_cast <typename MeshT::Color>(_color));
95  }
96 
97  void setPointSize(float /*_size*/ ) override {
98 
99  }
100 
101  void setIndex(int /*_size*/ ) override {
102 
103  }
104 
105  void request_vertex_normals() override {
106  mesh_.request_vertex_normals();
107  }
108 
109  void request_vertex_colors() override {
110  mesh_.request_vertex_colors();
111  }
112 
113  virtual void request_point_sizes() override {
114 
115  }
116 
117  virtual void request_indices() override {
118 
119  }
120 
121  void reserve(size_t _size) override {
122  mesh_.reserve(_size,0,0);
123  }
124 
125  virtual DataType adaptorType() override {
126  return type_;
127  }
128 
129 private :
130  MeshT& mesh_;
131  typename MeshT::VertexHandle currentPoint_;
132  DataType type_;
133 };
134 
135 
136 
137 
138 class AdaptorSplat : public AdaptorBase {
139 public:
140  AdaptorSplat(SplatCloud& _cloud) : cloud_(_cloud),splatIdx_(-1) {
141  cloud_.requestPositions();
142  }
143 
144  virtual ~AdaptorSplat() {
145 
146  }
147 
148  void clear() override {
149  cloud_.clear();
150  cloud_.requestPositions();
151  }
152 
153  void add_point(ACG::Vec3d _point) override {
154  ++splatIdx_;
155  cloud_.pushbackSplat();
156  cloud_.positions( splatIdx_ ) = _point;
157  }
158 
159  void setNormal(ACG::Vec3d _normal) override{
160  cloud_.normals( splatIdx_ ) = _normal;
161  }
162 
163  void setColor(ACG::Vec4f _color) override{
164  cloud_.colors( splatIdx_ ) = OpenMesh::color_cast<SplatCloud::Color>(_color);
165  }
166 
167  void setColor(ACG::Vec3uc _color) override{
168  cloud_.colors( splatIdx_) = _color;
169  }
170 
171  void setPointSize(float _size ) override {
172  cloud_.pointsizes(splatIdx_) = _size;
173  }
174 
175  void setIndex(int _index ) override {
176  cloud_.indices(splatIdx_) = _index;
177  }
178 
179  void request_vertex_normals() override {
180  cloud_.requestNormals();
181  }
182 
183  void request_vertex_colors() override {
184  cloud_.requestColors();
185  }
186 
187  virtual void request_point_sizes() override {
188  cloud_.requestPointsizes();
189  }
190 
191  virtual void request_indices() override {
192  cloud_.requestIndices();
193  }
194 
195  void reserve(size_t /*_size*/ ) override {
196  }
197 
198  virtual DataType adaptorType() override {
199  return DATA_SPLATCLOUD;
200  }
201 
202 private :
203  SplatCloud& cloud_;
204  int splatIdx_;
205 };
206 
207 
208 
209 FilePTSPlugin::FilePTSPlugin() :
210  loadOptions_( nullptr ),
211  saveOptions_( nullptr ),
212  saveBinaryFile_( nullptr ),
213  saveNormals_ ( nullptr ),
214  savePointsizes_( nullptr ),
215  saveColors_ ( nullptr ),
216  saveColorRange_( nullptr ),
217  saveIndices_ ( nullptr ),
218  saveMakeDefaultButton_( nullptr )
219 { }
220 
221 //----------------------------------------------------------------
222 
223 void FilePTSPlugin::initializePlugin()
224 {
225  QString info =
226  "This plugin is based on the Snappy compression library by google<br> "
227  "<br> "
228  "The following license applies to their code: <br> "
229  "Copyright 2005 Google Inc.All Rights Reserved. <br>"
230  " <br>"
231  "Redistribution and use in source and binary forms, with or without <br>"
232  "modification, are permitted provided that the following conditions are <br>"
233  "met : <br>"
234  " <br>"
235  " *Redistributions of source code must retain the above copyright <br>"
236  "notice, this list of conditions and the following disclaimer. <br>"
237  " * Redistributions in binary form must reproduce the above <br>"
238  "copyright notice, this list of conditions and the following disclaimer <br>"
239  "in the documentation and / or other materials provided with the <br>"
240  "distribution. <br>"
241  " * Neither the name of Google Inc.nor the names of its <br>"
242  "contributors may be used to endorse or promote products derived from <br>"
243  "this software without specific prior written permission. <br>"
244  " <br>"
245  "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS <br>"
246  "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT <br>"
247  "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR <br>"
248  "A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT <br>"
249  "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, <br>"
250  "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT <br>"
251  "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, <br>"
252  "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY <br>"
253  "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT <br>"
254  "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE <br>"
255  "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
256 
257  emit addAboutInfo(info, "FilePTS");
258 }
259 
260 //----------------------------------------------------------------
261 
262 namespace SplatDataFileFormat
263 {
264  // Standard Property Types (File Format)
265  enum STDPropTypes
266  {
267  FLOAT = 0,
268  FLOATVEC2 = 1,
269  FLOATVEC3 = 2,
270  DOUBLE = 3,
271  DOUBLEVEC2 = 4,
272  DOUBLEVEC3 = 5,
273  INT32 = 6,
274  INT32VEC2 = 7,
275  INT32VEC3 = 8,
276  INT16 = 9,
277  INT16VEC2 = 10,
278  INT16VEC3 = 11,
279  INT8 = 12,
280  INT8VEC2 = 13,
281  INT8VEC3 = 14,
282  UINT32 = 15,
283  UINT32VEC2 = 16,
284  UINT32VEC3 = 17,
285  UINT16 = 18,
286  UINT16VEC2 = 19,
287  UINT16VEC3 = 20,
288  UINT8 = 21,
289  UINT8VEC2 = 22,
290  UINT8VEC3 = 23,
291  INT32ARRAY = 24,
292  FLOATVEC2ARRAY = 25,
293  FLOATVEC3ARRAY = 26,
294  };
295 }
296 
297 
298 bool FilePTSPlugin::readBinaryFile( const char *_filename, SplatCloud &_splatCloud ) /*const*/
299 {
300  // clear splatcloud
301  _splatCloud.clear();
302 
303  // set default options
304  bool loadPositions = OpenFlipperSettings().value( "FilePTS/Load/Positions", true ).toBool();
305  bool loadNormals = OpenFlipperSettings().value( "FilePTS/Load/Normals", true ).toBool();
306  bool loadPointsizes = OpenFlipperSettings().value( "FilePTS/Load/Pointsizes", false ).toBool();
307  bool loadColors = OpenFlipperSettings().value( "FilePTS/Load/Colors", false ).toBool();
308 //int loadColorRange = 0;
309  bool loadIndices = OpenFlipperSettings().value( "FilePTS/Load/Indices", false ).toBool();
310 
311  // get options
312  if( OpenFlipper::Options::gui() && loadOptions_ )
313  {
314  loadPositions = loadOptions_->listWidget->findItems("Position",Qt::MatchExactly)[0]->isSelected();
315  loadNormals = loadOptions_->listWidget->findItems("Normal",Qt::MatchExactly)[0]->isSelected();
316  loadPointsizes = loadOptions_->listWidget->findItems("PointSize",Qt::MatchExactly)[0]->isSelected();
317  loadColors = loadOptions_->listWidget->findItems("Color",Qt::MatchExactly)[0]->isSelected();
318  loadIndices = loadOptions_->listWidget->findItems("Index",Qt::MatchExactly)[0]->isSelected();
319  }
320 
321  // request properties
322  bool success = true;
323  { if( !_splatCloud.requestPositions() ) success = false; }
324  if( loadNormals ) { if( !_splatCloud.requestNormals() ) success = false; }
325  if( loadPointsizes ) { if( !_splatCloud.requestPointsizes() ) success = false; }
326  if( loadColors ) { if( !_splatCloud.requestColors() ) success = false; }
327  if( loadIndices ) { if( !_splatCloud.requestIndices() ) success = false; }
328 
329  // check success of requests
330  if( !success )
331  {
332  emit log( LOGERR, tr("Out of memory for input file \"%1\".\n").arg( _filename ) );
333  return false; // return failure
334  }
335 
336  // open file
337  FILE *file = fopen( _filename, "rb" );
338  if( !file )
339  {
340  emit log( LOGERR, tr("Could not open input file \"%1\".\n").arg( _filename ) );
341  return false;
342  }
343 
344  // read file type
345  int fileType = 0;
346  fread( &fileType, sizeof(int), 1, file );
347 
348  // check file type
349  if( fileType != 1 && fileType != 2 && fileType != 3 )
350  {
351  emit log( LOGERR, tr("Bad filetype (%1) in input file \"%2\".\n").arg( QString::number( fileType ), _filename ) );
352  fclose( file );
353  return false; // return failure
354  }
355 
356  // read number of splats
357  unsigned int numSplats = 0;
358  fread( &numSplats, sizeof(unsigned int), 1, file );
359 
360  // set number of splats
361  _splatCloud.resizeSplats( numSplats );
362 
363  if (fileType < 3)
364  {
365  std::vector<ReadObject> readObject = getReadObjectOrder();
366 
367  for ( const ReadObject& element : readObject) {
368 
369 
370  // read positions
371  if ( element == PointPos)
372  {
373  unsigned int i;
374  for (i = 0; i < numSplats; ++i)
375  {
376  float pos[3];
377  fread(pos, sizeof(float), 3, file);
378 
379  SplatCloud::Position position;
380  position[0] = pos[0];
381  position[1] = pos[1];
382  position[2] = pos[2];
383 
384  _splatCloud.positions(i) = position;
385  }
386  }
387 
388  // read normals
389  if ( element == PointNormal && loadNormals)
390  {
391  unsigned int i;
392  for (i = 0; i < numSplats; ++i)
393  {
394  float nrm[3];
395  fread(nrm, sizeof(float), 3, file);
396 
397  SplatCloud::Normal normal;
398  normal[0] = nrm[0];
399  normal[1] = nrm[1];
400  normal[2] = nrm[2];
401 
402  _splatCloud.normals(i) = normal;
403  }
404  }
405 
406  // read pointsizes
407  if (element == PointSize && loadPointsizes)
408  {
409  unsigned int i;
410  for (i = 0; i < numSplats; ++i)
411  {
412  float ps = 0.0f;
413  fread(&ps, sizeof(float), 1, file);
414 
415  SplatCloud::Pointsize pointsize;
416  pointsize = ps;
417 
418  _splatCloud.pointsizes(i) = pointsize;
419  }
420  }
421 
422  // read colors
423  if (element == PointColor && loadColors)
424  {
425  unsigned int i;
426  for (i = 0; i < numSplats; ++i)
427  {
428  unsigned int col = 0;
429  fread(&col, sizeof(unsigned int), 1, file);
430 
431  SplatCloud::Color color; // ignore colorrange
432  color[0] = (unsigned char)((col >> 16) & 0xFF);
433  color[1] = (unsigned char)((col >> 8) & 0xFF);
434  color[2] = (unsigned char)((col) & 0xFF);
435 
436  _splatCloud.colors(i) = color;
437  }
438  }
439 
440  // read indices
441  if (element == PointIndex && loadIndices)
442  {
443  unsigned int i;
444  for (i = 0; i < numSplats; ++i)
445  {
446  int idx = -1;
447  fread(&idx, sizeof(idx), 1, file);
448 
449  SplatCloud::Index index;
450  index = idx;
451 
452  _splatCloud.indices(i) = index;
453  }
454  }
455 
456  }
457 
458  }
459  else if (fileType == 3)
460  {
461  // file contains named property containers
462 
463  int numProperties = 0;
464  fread(&numProperties, sizeof(int), 1, file);
465 
466  for (int propID = 0; propID < numProperties; ++propID)
467  {
468  // read property chunk
469 
470  // property name
471  int propNameLen = 0;
472  fread(&propNameLen, sizeof(int), 1, file);
473  std::string propName(propNameLen, 0);
474  if (propNameLen > 0)
475  fread(&propName[0], 1, propNameLen, file);
476 
477  // property data type
478  int dataType = 0;
479  fread(&dataType, sizeof(int), 1, file);
480 
481  // size of compressed data chunk
482  quint64 compressedSize = 0;
483  fread(&compressedSize, sizeof(quint64), 1, file);
484  size_t compressedSizeT = static_cast<size_t>(compressedSize);
485 
486  if (compressedSize)
487  {
488  // read data
489  if (dataType == SplatDataFileFormat::FLOATVEC3)
490  {
491  if (propName == "Points")
492  readCompressedBinaryChunk(file, compressedSizeT, reinterpret_cast<char*>(&_splatCloud.positions(0)));
493  else if (propName == "Normals" && loadNormals)
494  readCompressedBinaryChunk(file, compressedSizeT, reinterpret_cast<char*>(&_splatCloud.normals(0)));
495  else
496  fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
497  }
498  else if (dataType == SplatDataFileFormat::FLOAT)
499  {
500  if (propName == "Radii" && loadPointsizes)
501  readCompressedBinaryChunk(file, compressedSizeT, reinterpret_cast<char*>(&_splatCloud.pointsizes(0)));
502  else
503  fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
504  }
505  else if (dataType == SplatDataFileFormat::UINT16)
506  {
507  fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
508  }
509  else if (dataType == SplatDataFileFormat::UINT32)
510  {
511  if (propName == "Colors" && loadColors)
512  {
513  std::vector<ACG::Vec4uc> fileColors(numSplats);
514  readCompressedBinaryChunk(file, compressedSizeT, reinterpret_cast<char*>(&fileColors[0]));
515 
516  for (uint i = 0; i < numSplats; ++i)
517  {
518  for (int k = 0; k < 3; ++k)
519  _splatCloud.colors(i)[k] = fileColors[i][k];
520  }
521  }
522  else
523  fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
524  }
525  else if (dataType == SplatDataFileFormat::INT32)
526  {
527  fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
528  }
529  else
530  {
531  emit log(LOGWARN, tr("Unknown Property type. \"%1\".\n").arg(_filename));
532  fseek(file, static_cast<long>(compressedSizeT), SEEK_CUR);
533  }
534  }
535  }
536  }
537 
538 
539 
540  // check for errors
541  if( ferror( file ) )
542  {
543  emit log( LOGERR, tr("Could not read input file \"%1\".\n").arg( _filename ) );
544  fclose( file );
545  return false; // return failure
546  }
547  if( feof( file ) )
548  {
549  emit log( LOGERR, tr("Unexpected end in input file \"%1\".\n").arg( _filename ) );
550  fclose( file );
551  return false; // return failure
552  }
553 
554  // close file
555  fclose( file );
556 
557  // return success
558  return true;
559 }
560 
561 
562 //----------------------------------------------------------------
563 
564 
565 std::vector<ReadObject> FilePTSPlugin::getReadObjectOrder() {
566 
567  std::vector<ReadObject> readObject;
568 
569  for ( auto i = 0 ; i < loadOptions_->listWidget->count() ; ++i ) {
570  if ( loadOptions_->listWidget->item(i)->isSelected() ) {
571 
572  if (loadOptions_->listWidget->item(i)->text() == "Position" ) {
573  readObject.push_back(PointPos);
574  }
575 
576  if (loadOptions_->listWidget->item(i)->text() == "Normal" ) {
577  readObject.push_back(PointNormal);
578  }
579 
580  if (loadOptions_->listWidget->item(i)->text() == "Color" ) {
581  readObject.push_back(PointColor);
582  }
583 
584  if (loadOptions_->listWidget->item(i)->text() == "PointSize" ) {
585  readObject.push_back(PointSize);
586  }
587 
588  if (loadOptions_->listWidget->item(i)->text() == "Index" ) {
589  readObject.push_back(PointIndex);
590  }
591  }
592  }
593 
594  QString input_order;
595  for ( const ReadObject& i : readObject) {
596 
597  if ( i == PointPos )
598  input_order += " Position";
599  if ( i == PointNormal )
600  input_order += " Normal";
601  if ( i == PointColor )
602  input_order += " Color";
603  if ( i == PointSize )
604  input_order += " Pointsize";
605  if ( i == PointIndex )
606  input_order += " Index";
607  }
608 
609  emit log(LOGINFO,"Reading data in this order:" + input_order);
610 
611  return readObject;
612 }
613 
614 //----------------------------------------------------------------
615 
616 
617 bool FilePTSPlugin::readTextFile ( const char *_filename, AdaptorBase& _adaptor ) {
618  // clear Mesh
619  _adaptor.clear();
620 
621  // set default options
622  bool pointCount = OpenFlipperSettings().value( "FilePTS/Load/PointCount", true ).toBool();
623  bool loadNormals = OpenFlipperSettings().value( "FilePTS/Load/Normals", true ).toBool();
624  bool loadPointsizes = OpenFlipperSettings().value( "FilePTS/Load/Pointsizes", false ).toBool();
625  bool loadColors = OpenFlipperSettings().value( "FilePTS/Load/Colors", false ).toBool();
626  int loadColorRange = OpenFlipperSettings().value( "FilePTS/Load/ColorRange",0 ).toInt();
627  bool loadIndices = OpenFlipperSettings().value( "FilePTS/Load/Indices", false ).toBool();
628 
629 
630  std::vector<ReadObject> readObject = getReadObjectOrder();
631 
632 
633  if ( readObject[0] != PointPos ) {
634  emit log(LOGERR,"Position Attribute has to be first in the File!");
635  return false;
636  }
637 
638 
639 
640  // get options
641  if( OpenFlipper::Options::gui() && loadOptions_ )
642  {
643  loadNormals = loadOptions_->listWidget->findItems("Normal",Qt::MatchExactly)[0]->isSelected();
644  loadPointsizes = loadOptions_->listWidget->findItems("PointSize",Qt::MatchExactly)[0]->isSelected();
645  loadColors = loadOptions_->listWidget->findItems("Color",Qt::MatchExactly)[0]->isSelected();
646  loadIndices = loadOptions_->listWidget->findItems("Index",Qt::MatchExactly)[0]->isSelected();
647  pointCount = loadOptions_->pointCount->isChecked();
648  loadColorRange = loadOptions_->comboColor->currentIndex();
649 
650  }
651 
652  // request properties
653  if( loadNormals ) { _adaptor.request_vertex_normals(); }
654  if( loadColors ) { _adaptor.request_vertex_colors(); }
655  if( loadPointsizes ) { _adaptor.request_point_sizes(); }
656  if( loadIndices ) { _adaptor.request_indices(); }
657 
658 
659  QFile f(_filename);
660 
661  if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
662  emit log( LOGERR, tr("Could not open input file \"%1\".\n").arg( _filename ) );
663  return false;
664  }
665 
666  QTextStream in(&f);
667 
668  QString line = in.readLine();
669 
670  // We have a point count header. So parse it and allocate memory in advance
671  if (pointCount) {
672  bool ok;
673  const int size = line.toInt(&ok);
674  if ( ok ) {
675  emit log( LOGINFO, tr("Point count in header: \"%1\"").arg( size ) );
676  _adaptor.reserve(size);
677  } else {
678  emit log( LOGERR, tr("Failed to read point count header. Got \"%1\"").arg( line ) );
679  return false;
680  }
681  }
682 
683  int currentPoint = 0;
684  // Process all lines in file.
685  while (!in.atEnd()) {
686 
687  if ( (currentPoint % 100000) == 0 )
688  emit log( LOGINFO, tr("Reading point %1\n").arg( currentPoint ) );
689 
690  for ( const ReadObject& i : readObject) {
691 
692 
693  // Read a position, which should be always here:
694  if ( i == PointPos )
695  {
696  double pos[3];
697  in >> pos[0] >> pos[1] >> pos[2];
698  if ( in.status() == QTextStream::Ok ) {
699  _adaptor.add_point( TriMesh::Point(pos) );
700  } else {
701  emit log( LOGERR, tr("Failed to read postion for point %1\n").arg( currentPoint ) );
702  break;
703  }
704  }
705 
706  // Read color, if it has been selected
707  if( i == PointColor && loadColors )
708  {
709  if( loadColorRange == COLORRANGE_0_1 )
710  {
711  ACG::Vec4f color(0.0,0.0,0.0,1.0);
712 
713  in >> color[0] >> color[1] >> color[2];
714 
715  if ( in.status() == QTextStream::Ok ) {
716  _adaptor.setColor(color);
717  } else {
718  emit log( LOGERR, tr("Failed to read color for point %1\n").arg( currentPoint ) );
719  break;
720  }
721 
722  } else { // loadColorRange == COLORRANGE_0_255
723 
724  int col[3];
725 
726  in >> col[0] >> col[1] >> col[2];
727 
728 
729  ACG::Vec3uc color;
730 
731  color[0] = (unsigned char) col[0];
732  color[1] = (unsigned char) col[1];
733  color[2] = (unsigned char) col[2];
734 
735 
736  if ( in.status() == QTextStream::Ok ) {
737  _adaptor.setColor(color);
738  } else {
739  emit log( LOGERR, tr("Failed to read color for point %1\n").arg( currentPoint ) );
740  break;
741  }
742  }
743  }
744 
745  // read normal
746  if( i == PointNormal && loadNormals )
747  {
748  double nrm[3];
749  in >> nrm[0] >> nrm[1] >> nrm[2];
750 
751  if ( in.status() == QTextStream::Ok ) {
752  TriMesh::Normal normal;
753  normal[0] = nrm[0];
754  normal[1] = nrm[1];
755  normal[2] = nrm[2];
756 
757  _adaptor.setNormal(normal);
758  } else {
759  emit log( LOGERR, tr("Failed to read normal for point %1\n").arg( currentPoint ) );
760  break;
761  }
762 
763  }
764 
765  // read pointsize
766  if( i == PointSize && loadPointsizes )
767  {
768  float ps;
769 
770  in >> ps;
771 
772  if ( _adaptor.adaptorType() == DATA_SPLATCLOUD ) {
773  if ( in.status() == QTextStream::Ok ) {
774  _adaptor.setPointSize(ps);
775  } else {
776  emit log( LOGERR, tr("Failed to read point size for point %1\n").arg( currentPoint ) );
777  break;
778  }
779  } else
780  emit log(LOGERR, "Pointsize not implemented for meshes");
781 
782  }
783 
784  // read index
785  if( i == PointNormal && loadIndices )
786  {
787  int idx = -1;
788 
789  in >> idx;
790 
791  if ( _adaptor.adaptorType() == DATA_SPLATCLOUD ) {
792  if ( in.status() == QTextStream::Ok ) {
793  _adaptor.setIndex(idx);
794  } else {
795  emit log( LOGERR, tr("Failed to read index for point %1\n").arg( currentPoint ) );
796  break;
797  }
798  } else
799  emit log(LOGERR, "Index not implemented for meshes, skipped");
800 
801  }
802 
803  }
804 
805  ++currentPoint;
806  line = in.readLine();
807  //std::cerr << line.toStdString() << std::endl;
808  }
809 
810  if ( in.status() != QTextStream::Ok ) {
811  emit log( LOGERR, tr("Input File Stream Status not ok! Points read: %1\n").arg( currentPoint ) );
812  }
813 
814  // Sanity Check:
815  if ( !in.atEnd() ) {
816  emit log( LOGERR, tr("Not at end of file! Points read: %1\n").arg( currentPoint ) );
817  }
818 
819  f.close();
820 
821  // return success
822  return true;
823 
824 }
825 
826 //----------------------------------------------------------------
827 
828 
829 bool FilePTSPlugin::writeBinaryFile( const char *_filename, const SplatCloudNode *_splatCloudNode ) /*const*/
830 {
831  // set default options
832  bool saveNormals = OpenFlipperSettings().value( "FilePTS/Save/Normals", true ).toBool();
833  bool savePointsizes = OpenFlipperSettings().value( "FilePTS/Save/Pointsizes", false ).toBool();
834  bool saveColors = OpenFlipperSettings().value( "FilePTS/Save/Colors", false ).toBool();
835 //int saveColorRange = 0;
836  bool saveIndices = OpenFlipperSettings().value( "FilePTS/Save/Indices", false ).toBool();
837 
838  // get options
839  if( OpenFlipper::Options::gui() && saveOptions_ )
840  {
841  saveNormals = saveNormals_-> isChecked();
842  savePointsizes = savePointsizes_->isChecked();
843  saveColors = saveColors_-> isChecked();
844 // saveColorRange = saveColorRange_->currentIndex();
845  saveIndices = saveIndices_-> isChecked();
846  }
847 
848  // use default values instead of returning a failure
849 
851 //if( ( !_splatCloudNode->splatCloud().hasPositions() ) ||
852 // (saveNormals && !_splatCloudNode->splatCloud().hasNormals()) ) ||
853 // (savePointsizes && !_splatCloudNode->splatCloud().hasPointsizes()) ||
854 // (saveColors && !_splatCloudNode->splatCloud().hasColors() ) ||
855 // (saveIndices && !_splatCloudNode->splatCloud().hasIndices() )
856 //{
857 // emit log( LOGERR, tr("Desired properties not available for output file \"%1\".\n").arg( _filename ) );
858 // return false; // return failure
859 //}
860 
861  // open file
862  FILE *file = fopen( _filename, "wb" );
863  if( !file )
864  {
865  emit log( LOGERR, tr("Could not open output file \"%1\".\n").arg( _filename ) );
866  return false;
867  }
868 
869  // write file type
870  int fileType = 1;
871  fwrite( &fileType, sizeof(int), 1, file );
872 
873  // write number of splats
874  unsigned int numSplats = _splatCloudNode->splatCloud().numSplats();
875  fwrite( &numSplats, sizeof(unsigned int), 1, file );
876 
877  // write positions
878  {
879  unsigned int i;
880  for( i=0; i<numSplats; ++i )
881  {
882  const SplatCloud::Position &position = _splatCloudNode->getPosition( i );
883 
884  float pos[3];
885  pos[0] = position[0];
886  pos[1] = position[1];
887  pos[2] = position[2];
888 
889  fwrite( pos, sizeof(float), 3, file );
890  }
891  }
892 
893  // write normals
894  if( saveNormals )
895  {
896  unsigned int i;
897  for( i=0; i<numSplats; ++i )
898  {
899  const SplatCloud::Normal &normal = _splatCloudNode->getNormal( i );
900 
901  float nrm[3];
902  nrm[0] = normal[0];
903  nrm[1] = normal[1];
904  nrm[2] = normal[2];
905 
906  fwrite( nrm, sizeof(float), 3, file );
907  }
908  }
909 
910  // write pointsizes
911  if( savePointsizes )
912  {
913  unsigned int i;
914  for( i=0; i<numSplats; ++i )
915  {
916  const SplatCloud::Pointsize &pointsize = _splatCloudNode->getPointsize( i );
917 
918  float ps;
919  ps = pointsize;
920 
921  fwrite( &ps, sizeof(float), 1, file );
922  }
923  }
924 
925  // write colors
926  if( saveColors )
927  {
928  unsigned int i;
929  for( i=0; i<numSplats; ++i )
930  {
931  const SplatCloud::Color &color = _splatCloudNode->getColor( i );
932 
933  unsigned int col; // ignore colorrange
934  col = (0xFF << 24) | (color[0] << 16) | (color[1] << 8) | (color[2]);
935 
936  fwrite( &col, sizeof(unsigned int), 1, file );
937  }
938  }
939 
940  // write indices
941  if( saveIndices )
942  {
943  unsigned int i;
944  for( i=0; i<numSplats; ++i )
945  {
946  const SplatCloud::Index &index = _splatCloudNode->getIndex( i );
947 
948  int idx;
949  idx = index;
950 
951  fwrite( &idx, sizeof(int), 1, file );
952  }
953  }
954 
955  // check for errors
956  if( ferror( file ) )
957  {
958  emit log( LOGERR, tr("Could not write output file \"%1\".\n").arg( _filename ) );
959  fclose( file );
960  return false; // return failure
961  }
962 
963  // close file
964  fclose( file );
965 
966  // return success
967  return true;
968 }
969 
970 
971 //----------------------------------------------------------------
972 
973 
974 bool FilePTSPlugin::writeTextFile( const char *_filename, const SplatCloudNode *_splatCloudNode ) /*const*/
975 {
976  // set default options
977  bool saveNormals = OpenFlipperSettings().value( "FilePTS/Save/Normals", true ).toBool();
978  bool savePointsizes = OpenFlipperSettings().value( "FilePTS/Save/Pointsizes", false ).toBool();
979  bool saveColors = OpenFlipperSettings().value( "FilePTS/Save/Colors", false ).toBool();
980  int saveColorRange = OpenFlipperSettings().value( "FilePTS/Save/ColorRange",0 ).toInt();
981  bool saveIndices = OpenFlipperSettings().value( "FilePTS/Save/Indices", false ).toBool();
982 
983  // get options
984  if( OpenFlipper::Options::gui() && saveOptions_ )
985  {
986  saveNormals = saveNormals_-> isChecked();
987  savePointsizes = savePointsizes_->isChecked();
988  saveColors = saveColors_-> isChecked();
989  saveColorRange = saveColorRange_->currentIndex();
990  saveIndices = saveIndices_-> isChecked();
991  }
992 
993  // open file
994  FILE *file = fopen( _filename, "wt" );
995  if( !file )
996  {
997  emit log( LOGERR, tr("Could not open output file \"%1\".\n").arg( _filename ) );
998  return false;
999  }
1000 
1001  // for all splats...
1002  unsigned int i, numSplats = _splatCloudNode->splatCloud().numSplats();
1003  for( i=0; i<numSplats; ++i )
1004  {
1005  // write position
1006  {
1007  const SplatCloud::Position &position = _splatCloudNode->getPosition( i );
1008 
1009  float pos[3];
1010  pos[0] = position[0];
1011  pos[1] = position[1];
1012  pos[2] = position[2];
1013 
1014  fprintf( file, "%.6g %.6g %.6g", pos[0], pos[1], pos[2] );
1015  }
1016 
1017  // write color
1018  if( saveColors )
1019  {
1020  const SplatCloud::Color &color = _splatCloudNode->getColor( i );
1021 
1022  if( saveColorRange == COLORRANGE_0_1 )
1023  {
1024  static const float RCP255 = 1.0f / 255.0f;
1025 
1026  float col[3];
1027  col[0] = RCP255 * color[0];
1028  col[1] = RCP255 * color[1];
1029  col[2] = RCP255 * color[2];
1030 
1031  fprintf( file, " %.6g %.6g %.6g", col[0], col[1], col[2] );
1032  }
1033  else // saveColorRange == COLORRANGE_0_255
1034  {
1035  int col[3]; // use int, *not* unsigned char !
1036  col[0] = color[0];
1037  col[1] = color[1];
1038  col[2] = color[2];
1039 
1040  fprintf( file, " %i %i %i", col[0], col[1], col[2] );
1041  }
1042  }
1043 
1044  // write normal
1045  if( saveNormals )
1046  {
1047  const SplatCloud::Normal &normal = _splatCloudNode->getNormal( i );
1048 
1049  float nrm[3];
1050  nrm[0] = normal[0];
1051  nrm[1] = normal[1];
1052  nrm[2] = normal[2];
1053 
1054  fprintf( file, " %.6g %.6g %.6g", nrm[0], nrm[1], nrm[2] );
1055  }
1056 
1057  // write pointsize
1058  if( savePointsizes )
1059  {
1060  const SplatCloud::Pointsize &pointsize = _splatCloudNode->getPointsize( i );
1061 
1062  float ps;
1063  ps = pointsize;
1064 
1065  fprintf( file, " %.6g", ps );
1066  }
1067 
1068  // write index
1069  if( saveIndices )
1070  {
1071  const SplatCloud::Index &index = _splatCloudNode->getIndex( i );
1072 
1073  int idx;
1074  idx = index;
1075 
1076  fprintf( file, " %i", idx );
1077  }
1078 
1079  fprintf( file, "\n" );
1080  }
1081 
1082  // check for errors
1083  if( ferror( file ) )
1084  {
1085  emit log( LOGERR, tr("Could not write output file \"%1\".\n").arg( _filename ) );
1086  fclose( file );
1087  return false; // return failure
1088  }
1089 
1090  // close file
1091  fclose( file );
1092 
1093  // return success
1094  return true;
1095 }
1096 
1097 
1098 //----------------------------------------------------------------
1099 
1100 
1101 bool FilePTSPlugin::readCompressedBinaryChunk(FILE* _file, size_t _compressedSize, char* _dst)
1102 {
1103  std::vector<char> compressedData(_compressedSize);
1104  fread(&compressedData[0], 1, _compressedSize, _file);
1105  return snappy::RawUncompress(&compressedData[0], _compressedSize, _dst);
1106 }
1107 
1108 //----------------------------------------------------------------
1109 
1110 
1111 int FilePTSPlugin::loadObject( QString _filename )
1112 {
1113  // set default options
1114  bool loadBinaryFile = OpenFlipperSettings().value( "FilePTS/Load/BinaryFile", false ).toBool();
1115  enum dataType{ splatcloud,
1116  trianglemesh,
1117  polymesh } loadType = splatcloud;
1118  // get options
1119  if( OpenFlipper::Options::gui() && loadOptions_ )
1120  {
1121  if (loadOptions_->type->currentText() == "TriangleMesh") {
1122  loadType = trianglemesh;
1123  } else if (loadOptions_->type->currentText() == "PolyMesh") {
1124  loadType = polymesh;
1125  } else {
1126  loadType = splatcloud;
1127  }
1128 
1129  loadBinaryFile = loadOptions_->binary->isChecked();
1130  }
1131 
1132 
1133  if ( loadType == splatcloud ) {
1134 
1135  // add a new, empty splatcloud-object
1136  int splatCloudObjectId = -1;
1137  emit addEmptyObject( DATA_SPLATCLOUD, splatCloudObjectId );
1138  if( splatCloudObjectId != -1 )
1139  {
1140  // create list of ids and add id of splatcloud-object
1141  IdList objectIDs;
1142  objectIDs.push_back( splatCloudObjectId );
1143 
1144  // get splatcloud-object by id
1145  SplatCloudObject *splatCloudObject = 0;
1146  if( PluginFunctions::getObject( splatCloudObjectId, splatCloudObject ) )
1147  {
1148  // set name of splatcloud-object to filename
1149  splatCloudObject->setFromFileName( _filename );
1150  splatCloudObject->setName( splatCloudObject->filename() );
1151 
1152  // get splatcloud and scenegraph splatcloud-node
1153  SplatCloud *splatCloud = splatCloudObject->splatCloud();
1154  SplatCloudNode *splatCloudNode = splatCloudObject->splatCloudNode();
1155  if( (splatCloud != 0) && (splatCloudNode != 0) )
1156  {
1157  AdaptorSplat adaptor(*splatCloud);
1158 
1159  // read splatcloud from disk
1160  if( loadBinaryFile ? readBinaryFile( _filename.toLatin1(), *splatCloud ) : readTextFile( _filename.toLatin1(), adaptor ) )
1161  {
1162  // emit signals that the object has to be updated and that a file was opened
1163  emit updatedObject( splatCloudObjectId, UPDATE_ALL );
1164  emit openedFile( splatCloudObjectId );
1165 
1166  // get drawmodes
1170 
1171  // if drawmodes don't exist something went wrong
1172  if( splatsDrawMode == ACG::SceneGraph::DrawModes::NONE ||
1173  dotsDrawMode == ACG::SceneGraph::DrawModes::NONE ||
1174  pointsDrawMode == ACG::SceneGraph::DrawModes::NONE )
1175  {
1176  emit log( LOGERR, tr("Shader DrawModes for SplatCloud not existent!") );
1177  }
1178  else
1179  {
1180  // get global drawmode
1182 
1183  // if global drawmode does *not* contain any of 'Splats', 'Dots' or 'Points' drawmode, add 'Points'
1184  if( !drawmode.containsAtomicDrawMode( splatsDrawMode ) &&
1185  !drawmode.containsAtomicDrawMode( dotsDrawMode ) &&
1186  !drawmode.containsAtomicDrawMode( pointsDrawMode ) )
1187  {
1188  drawmode |= pointsDrawMode;
1189  PluginFunctions::setDrawMode( drawmode );
1190  }
1191  }
1192 
1193  // group objects
1194  int groupObjectId = RPC::callFunctionValue<int>( "datacontrol", "groupObjects", objectIDs );
1195  if( groupObjectId != -1 )
1196  {
1197  // everything is okay, so return id of group-object
1198  return groupObjectId;
1199  }
1200  }
1201  }
1202  }
1203 
1204  // something went wrong, so delete objects
1205  size_t i, num = objectIDs.size();
1206  for( i=0; i<num; ++i )
1207  emit deleteObject( objectIDs[ i ] );
1208  }
1209  } else if ( loadType == trianglemesh ) {
1210 
1211  // add a new, empty splatcloud-object
1212  int triangleMeshID = -1;
1213  emit addEmptyObject( DATA_TRIANGLE_MESH, triangleMeshID );
1214  if( triangleMeshID != -1 ) {
1215 
1216  // get splatcloud-object by id
1217  TriMeshObject *triObject = 0;
1218  if( PluginFunctions::getObject( triangleMeshID, triObject ) )
1219  {
1220  // set name of splatcloud-object to filename
1221  triObject->setFromFileName( _filename );
1222  triObject->setName( triObject->filename() );
1223 
1224  // get splatcloud and scenegraph splatcloud-node
1225  TriMesh *mesh = triObject->mesh();
1226 
1227  if( mesh != 0 ) {
1228  if ( loadBinaryFile ) {
1229  emit log(LOGERR,"Binary not supported for mesh target!");
1230  } else {
1232 
1233  readTextFile( _filename.toLatin1(), adaptor ) ;
1234 
1235  // emit signals that the object has to be updated and that a file was opened
1236  emit updatedObject( triangleMeshID, UPDATE_ALL );
1237  emit openedFile( triangleMeshID );
1238 
1240 
1241  triObject->meshNode()->drawMode(pointsDrawMode);
1242  return triangleMeshID;
1243  }
1244  }
1245  }
1246  }
1247  } else { // PolyMesh
1248 
1249  // add a new, empty splatcloud-object
1250  int polyMeshID = -1;
1251  emit addEmptyObject( DATA_POLY_MESH, polyMeshID );
1252  if( polyMeshID != -1 ) {
1253 
1254  // get splatcloud-object by id
1255  PolyMeshObject *triObject = 0;
1256  if( PluginFunctions::getObject( polyMeshID, triObject ) )
1257  {
1258  // set name of splatcloud-object to filename
1259  triObject->setFromFileName( _filename );
1260  triObject->setName( triObject->filename() );
1261 
1262  // get splatcloud and scenegraph splatcloud-node
1263  PolyMesh *mesh = triObject->mesh();
1264 
1265  if( mesh != 0 ) {
1266  if ( loadBinaryFile ) {
1267  emit log(LOGERR,"Binary not supported for mesh target!");
1268  } else {
1269  AdaptorMesh<PolyMesh> adaptor(*mesh,DATA_POLY_MESH);
1270 
1271  readTextFile( _filename.toLatin1(), adaptor ) ;
1272 
1273  // emit signals that the object has to be updated and that a file was opened
1274  emit updatedObject( polyMeshID, UPDATE_ALL );
1275  emit openedFile( polyMeshID );
1276 
1278 
1279  triObject->meshNode()->drawMode(pointsDrawMode);
1280  return polyMeshID;
1281  }
1282  }
1283  }
1284  }
1285  }
1286 
1287  // return failure
1288  return -1;
1289 }
1290 
1291 
1292 //----------------------------------------------------------------
1293 
1294 
1295 bool FilePTSPlugin::saveObject( int _objectId, QString _filename )
1296 {
1297  // set default options
1298  bool saveBinaryFile = OpenFlipperSettings().value( "FilePTS/Save/BinaryFile", false ).toBool();
1299 
1300  // get options
1301  if( OpenFlipper::Options::gui() && saveOptions_ )
1302  {
1303  saveBinaryFile = saveBinaryFile_->isChecked();
1304  }
1305 
1306  // get splatcloud-object by id
1307  SplatCloudObject *splatCloudObject = 0;
1308  if( PluginFunctions::getObject( _objectId, splatCloudObject ) )
1309  {
1310  // change name of splatcloud-object to filename
1311  splatCloudObject->setFromFileName( _filename );
1312  splatCloudObject->setName( splatCloudObject->filename() );
1313 
1314  // get splatcloud-node
1315  const SplatCloudNode *splatCloudNode = splatCloudObject->splatCloudNode();
1316  if( splatCloudNode != 0 )
1317  {
1318  // write splatcloud to disk
1319  if( saveBinaryFile ? writeBinaryFile( _filename.toLatin1(), splatCloudNode ) : writeTextFile( _filename.toLatin1(), splatCloudNode ) )
1320  {
1321  // return success
1322  return true;
1323  }
1324  }
1325  }
1326 
1327  // return failure
1328  return false;
1329 }
1330 
1331 
1332 //----------------------------------------------------------------
1333 
1334 
1335 QWidget *FilePTSPlugin::loadOptionsWidget( QString /*_currentFilter*/ )
1336 {
1337  if ( loadOptions_ == nullptr) {
1338  loadOptions_ = new ptsLoadWiget();
1339 
1340 
1341  QStringList order = OpenFlipperSettings().value( "FilePTS/Load/Order", "position,normal,color,size,index" ).toString().split(",");
1342 
1343  loadOptions_->listWidget->clear();
1344 
1345  for ( const QString& name : order ) {
1346 
1347  if ( name == "position" ) {
1348  loadOptions_->listWidget->addItem("Position");
1349  }
1350 
1351  if ( name == "normal" ) {
1352  loadOptions_->listWidget->addItem("Normal");
1353  }
1354 
1355  if ( name == "color" ) {
1356  loadOptions_->listWidget->addItem("Color");
1357  }
1358 
1359  if ( name == "size" ) {
1360  loadOptions_->listWidget->addItem("PointSize");
1361  }
1362 
1363  if ( name == "index" ) {
1364  loadOptions_->listWidget->addItem("Index");
1365  }
1366 
1367  }
1368 
1369  loadOptions_->type->setCurrentIndex ( OpenFlipperSettings().value( "FilePTS/Load/LoadType", 0 ).toInt() );
1370  loadOptions_->binary->setChecked ( OpenFlipperSettings().value( "FilePTS/Load/BinaryFile", true ).toBool() );
1371  loadOptions_->pointCount->setChecked ( OpenFlipperSettings().value( "FilePTS/Load/PointCount", true ).toBool() );
1372  loadOptions_->listWidget->findItems("Position",Qt::MatchExactly)[0]->setSelected( OpenFlipperSettings().value( "FilePTS/Load/Position", true ).toBool() );
1373  loadOptions_->listWidget->findItems("Normal",Qt::MatchExactly)[0]->setSelected( OpenFlipperSettings().value( "FilePTS/Load/Normals", true ).toBool() );
1374  loadOptions_->listWidget->findItems("PointSize",Qt::MatchExactly)[0]->setSelected(OpenFlipperSettings().value( "FilePTS/Load/Pointsizes", true ).toBool()) ;
1375  loadOptions_->comboColor->setCurrentIndex(OpenFlipperSettings().value( "FilePTS/Load/ColorRange", 0 ).toInt() );
1376  loadOptions_->listWidget->findItems("Color",Qt::MatchExactly)[0]->setSelected(OpenFlipperSettings().value( "FilePTS/Load/Colors", true ).toBool()) ;
1377  loadOptions_->listWidget->findItems("Index",Qt::MatchExactly)[0]->setSelected(OpenFlipperSettings().value( "FilePTS/Load/Indices", true ).toBool() );
1378 
1379  connect(loadOptions_->defaultButton,SIGNAL( clicked() ) , this, SLOT(slotLoadMakeDefaultButtonClicked() ) );
1380  connect(loadOptions_->defaultButton,SIGNAL( clicked() ) , this, SLOT(slotLoadMakeDefaultButtonClicked() ) );
1381 
1382  }
1383 
1384  return loadOptions_;
1385 }
1386 
1387 
1388 //----------------------------------------------------------------
1389 
1390 
1391 QWidget *FilePTSPlugin::saveOptionsWidget( QString _currentFilter )
1392 {
1393  if( saveOptions_ == 0 )
1394  {
1395  // create new widget (including Save Options and buttons)
1396 
1397  saveBinaryFile_ = new QCheckBox( tr("Save as Binary File") );
1398 
1399  saveNormals_ = new QCheckBox( tr("Save Normals") );
1400  savePointsizes_ = new QCheckBox( tr("Save Pointsizes") );
1401  saveColors_ = new QCheckBox( tr("Save Colors") );
1402 
1403  saveColorRange_ = new QComboBox();
1404  saveColorRange_->addItem( "[0..1]" );
1405  saveColorRange_->addItem( "[0..255]" );
1406  slotUpdateSaveColorRange();
1407 
1408  QHBoxLayout *saveColorsLayout = new QHBoxLayout();
1409  saveColorsLayout->setSpacing( 6 );
1410  saveColorsLayout->addWidget( saveColors_ );
1411  saveColorsLayout->addWidget( saveColorRange_ );
1412 
1413  saveIndices_ = new QCheckBox( tr("Save Indices") );
1414 
1415  QVBoxLayout *saveStructureLayout = new QVBoxLayout();
1416  saveStructureLayout->setSpacing( 6 );
1417  saveStructureLayout->addWidget( saveNormals_ );
1418  saveStructureLayout->addWidget( savePointsizes_ );
1419  saveStructureLayout->addItem ( saveColorsLayout );
1420  saveStructureLayout->addWidget( saveIndices_ );
1421 
1422  QGroupBox *saveStructureGroupBox = new QGroupBox( tr("Internal File Structure") );
1423  saveStructureGroupBox->setLayout( saveStructureLayout );
1424 
1425  saveMakeDefaultButton_ = new QPushButton( tr("Make Default") );
1426 
1427  QVBoxLayout *saveLayout = new QVBoxLayout();
1428  saveLayout->setAlignment( Qt::AlignTop );
1429  saveLayout->setSpacing( 6 );
1430  saveLayout->addWidget( saveBinaryFile_ );
1431  saveLayout->addWidget( saveStructureGroupBox );
1432  saveLayout->addWidget( saveMakeDefaultButton_ );
1433 
1434  saveOptions_ = new QWidget();
1435  saveOptions_->setLayout( saveLayout );
1436 
1437  // connect events to slots
1438  connect( saveBinaryFile_, SIGNAL( stateChanged(int) ), this, SLOT( slotUpdateSaveColorRange() ) );
1439  connect( saveColors_, SIGNAL( stateChanged(int) ), this, SLOT( slotUpdateSaveColorRange() ) );
1440  connect( saveMakeDefaultButton_, SIGNAL( clicked() ), this, SLOT( slotSaveMakeDefaultButtonClicked() ) );
1441 
1442  // get Save Options from OpenFlipper (from disc)
1443  saveBinaryFile_->setChecked ( OpenFlipperSettings().value( "FilePTS/Save/BinaryFile", true ).toBool() );
1444  saveNormals_-> setChecked ( OpenFlipperSettings().value( "FilePTS/Save/Normals", true ).toBool() );
1445  savePointsizes_->setChecked ( OpenFlipperSettings().value( "FilePTS/Save/Pointsizes", true ).toBool() );
1446  saveColors_-> setChecked ( OpenFlipperSettings().value( "FilePTS/Save/Colors", true ).toBool() );
1447  saveColorRange_->setCurrentIndex( OpenFlipperSettings().value( "FilePTS/Save/ColorRange", 0 ).toInt() );
1448  saveIndices_-> setChecked ( OpenFlipperSettings().value( "FilePTS/Save/Indices", true ).toBool() );
1449  }
1450 
1451  return saveOptions_;
1452 }
1453 
1454 
1455 //----------------------------------------------------------------
1456 
1457 void FilePTSPlugin::slotUpdateSaveColorRange()
1458 {
1459  saveColorRange_->setEnabled( saveColors_->isChecked() && !saveBinaryFile_->isChecked() );
1460 }
1461 
1462 
1463 //----------------------------------------------------------------
1464 
1465 
1466 void FilePTSPlugin::slotLoadMakeDefaultButtonClicked()
1467 {
1468 
1469  // pass our Load Options to OpenFlipper (to disc)
1470  OpenFlipperSettings().setValue( "FilePTS/Load/LoadType", loadOptions_->type->currentIndex() );
1471  OpenFlipperSettings().setValue( "FilePTS/Load/PointCount", loadOptions_->pointCount->isChecked() );
1472  OpenFlipperSettings().setValue( "FilePTS/Load/BinaryFile", loadOptions_->binary->isChecked() );
1473  OpenFlipperSettings().setValue( "FilePTS/Load/Positions", loadOptions_->listWidget->findItems("Position",Qt::MatchExactly)[0]->isSelected() );
1474  OpenFlipperSettings().setValue( "FilePTS/Load/Normals", loadOptions_->listWidget->findItems("Normal",Qt::MatchExactly)[0]->isSelected() );
1475  OpenFlipperSettings().setValue( "FilePTS/Load/Pointsizes", loadOptions_->listWidget->findItems("PointSize",Qt::MatchExactly)[0]->isSelected() );
1476  OpenFlipperSettings().setValue( "FilePTS/Load/Colors", loadOptions_->listWidget->findItems("Color",Qt::MatchExactly)[0]->isSelected() );
1477  OpenFlipperSettings().setValue( "FilePTS/Load/ColorRange", loadOptions_->comboColor->currentIndex() );
1478  OpenFlipperSettings().setValue( "FilePTS/Load/Indices", loadOptions_->listWidget->findItems("Index",Qt::MatchExactly)[0]->isSelected() );
1479 
1480  QString order = "";
1481 
1482  for ( auto i = 0 ; i < loadOptions_->listWidget->count() ; ++i ) {
1483  if (loadOptions_->listWidget->item(i)->text() == "Position" ) {
1484  order +="position,";
1485  }
1486 
1487  if (loadOptions_->listWidget->item(i)->text() == "Normal" ) {
1488  order +="normal,";
1489  }
1490 
1491  if (loadOptions_->listWidget->item(i)->text() == "Color" ) {
1492  order +="color,";
1493  }
1494 
1495  if (loadOptions_->listWidget->item(i)->text() == "PointSize" ) {
1496  order +="size,";
1497  }
1498 
1499  if (loadOptions_->listWidget->item(i)->text() == "Index" ) {
1500  order +="index,";
1501  }
1502  }
1503 
1504  // remove last ","
1505  order.chop(1);
1506 
1507  OpenFlipperSettings().setValue( "FilePTS/Load/Order", order );
1508 }
1509 
1510 
1511 //----------------------------------------------------------------
1512 
1513 
1514 void FilePTSPlugin::slotSaveMakeDefaultButtonClicked()
1515 {
1516  // pass our Save Options to OpenFlipper (to disc)
1517  OpenFlipperSettings().setValue( "FilePTS/Save/BinaryFile", saveBinaryFile_->isChecked() );
1518  OpenFlipperSettings().setValue( "FilePTS/Save/Normals", saveNormals_-> isChecked() );
1519  OpenFlipperSettings().setValue( "FilePTS/Save/Pointsizes", savePointsizes_->isChecked() );
1520  OpenFlipperSettings().setValue( "FilePTS/Save/Colors", saveColors_-> isChecked() );
1521  OpenFlipperSettings().setValue( "FilePTS/Save/ColorRange", saveColorRange_->currentIndex() );
1522  OpenFlipperSettings().setValue( "FilePTS/Save/Indices", saveIndices_-> isChecked() );
1523 }
1524 
1525 
1526 //================================================================
1527 
Position & positions(int _idx)
Get a reference of the predefined property&#39;s value.
Definition: SplatCloud.hh:631
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
#define DATA_POLY_MESH
Definition: PolyMesh.hh:59
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
unsigned int numSplats() const
Get the number of splats.
Definition: SplatCloud.hh:179
Kernel::Normal Normal
Normal type.
Definition: PolyMeshT.hh:114
Type for a Meshobject containing a poly mesh.
Definition: PolyMesh.hh:65
Color & colors(int _idx)
Get a reference of the predefined property&#39;s value.
Definition: SplatCloud.hh:633
DrawModes::DrawMode drawMode() const
Return the own draw modes of this node.
Definition: BaseNode.hh:430
bool containsAtomicDrawMode(const DrawMode &_atomicDrawMode) const
Check whether an Atomic DrawMode is active in this draw Mode.
Definition: DrawModes.cc:512
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
bool requestPositions()
Request the predefined property.
Definition: SplatCloud.hh:561
ACG::SceneGraph::DrawModes::DrawMode drawMode(int _viewer)
Get the current draw Mode of a Viewer.
#define DATA_SPLATCLOUD
Definition: SplatCloud.hh:59
Predefined datatypes.
Definition: DataTypes.hh:83
SplatCloud * splatCloud()
Get SplatCloud.
void setName(QString _name)
Set the name of the Object.
QString filename() const
return the filename of the object
Definition: BaseObject.cc:706
MeshT * mesh()
return a pointer to the mesh
std::vector< int > IdList
Standard Type for id Lists used for scripting.
Definition: DataTypes.hh:181
void setName(QString _name)
Set the name of the Object.
bool requestColors()
Request the predefined property.
Definition: SplatCloud.hh:562
const DrawMode & getDrawMode(const std::string &_name)
Get a custom DrawMode.
Definition: DrawModes.cc:799
Normal & normals(int _idx)
Get a reference of the predefined property&#39;s value.
Definition: SplatCloud.hh:635
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
bool requestPointsizes()
Request the predefined property.
Definition: SplatCloud.hh:564
Pointsize & pointsizes(int _idx)
Get a reference of the predefined property&#39;s value.
Definition: SplatCloud.hh:637
bool requestIndices()
Request the predefined property.
Definition: SplatCloud.hh:565
DrawMode NONE
not a valid draw mode
Definition: DrawModes.cc:71
Type for a MeshObject containing a triangle mesh.
Definition: TriangleMesh.hh:67
void clear()
Remove all properties and reset the number of splats.
Definition: SplatCloud.cc:184
ACG::SceneGraph::MeshNodeT< MeshT > * meshNode()
Get the Scenegraph Mesh Node.
void setDrawMode(const ACG::SceneGraph::DrawModes::DrawMode &_mode, int _viewer)
Set the draw Mode of a Viewer. .
QWidget * loadOptionsWidget(QString)
Definition: FilePTS.cc:1335
const Position & getPosition(int _idx) const
if the data array exists, the entry with the given index is returned, otherwise the default value is ...
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
SplatCloudNode * splatCloudNode()
Get SplatCloud&#39;s scenegraph Node.
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
Index & indices(int _idx)
Get a reference of the predefined property&#39;s value.
Definition: SplatCloud.hh:639
bool requestNormals()
Request the predefined property.
Definition: SplatCloud.hh:563
void resizeSplats(unsigned int _num)
Resize the data vector of all splat-properties.
Definition: SplatCloud.cc:246
void setFromFileName(const QString &_filename)
Definition: BaseObject.cc:716
QWidget * saveOptionsWidget(QString)
Definition: FilePTS.cc:1391