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