FilePTS.cc 31.8 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
2
3
4
//================================================================
//
/*===========================================================================*\
*                                                                            *
Jan Möbius's avatar
Jan Möbius committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 *                              OpenFlipper                                   *
 *      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen       *
 *                           www.openflipper.org                              *
 *                                                                            *
 *--------------------------------------------------------------------------- *
 *  This file is part of OpenFlipper.                                         *
 *                                                                            *
 *  OpenFlipper is free software: you can redistribute it and/or modify       *
 *  it under the terms of the GNU Lesser General Public License as            *
 *  published by the Free Software Foundation, either version 3 of            *
 *  the License, or (at your option) any later version with the               *
 *  following exceptions:                                                     *
 *                                                                            *
 *  If other files instantiate templates or use macros                        *
 *  or inline functions from this file, or you compile this file and          *
 *  link it with other files to produce an executable, this file does         *
 *  not by itself cause the resulting executable to be covered by the         *
 *  GNU Lesser General Public License. This exception does not however        *
 *  invalidate any other reasons why the executable file might be             *
 *  covered by the GNU Lesser General Public License.                         *
 *                                                                            *
 *  OpenFlipper is distributed in the hope that it will be useful,            *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 *  GNU Lesser General Public License for more details.                       *
 *                                                                            *
 *  You should have received a copy of the GNU LesserGeneral Public           *
 *  License along with OpenFlipper. If not,                                   *
 *  see <http://www.gnu.org/licenses/>.                                       *
 *                                                                            *
 \*===========================================================================*/
Jan Möbius's avatar
Jan Möbius committed
36
37
38

/*===========================================================================*\
*                                                                            *
Jan Möbius's avatar
Jan Möbius committed
39
40
41
42
43
 *   $Revision$                                                       *
 *   $LastChangedBy$                                                *
 *   $Date$                     *
 *                                                                            *
 \*===========================================================================*/
Jan Möbius's avatar
Jan Möbius committed
44

45

Jan Möbius's avatar
Jan Möbius committed
46
47
48
49
50
//================================================================
//
//  CLASS FilePTSPlugin - IMPLEMENTATION
//
//================================================================
51
52


Jan Möbius's avatar
Jan Möbius committed
53
//== INCLUDES ====================================================
54
55


Jan Möbius's avatar
Jan Möbius committed
56
57
58
59
60
61
#include "FilePTS.hh"

#include <QtGui>
#include <QFileInfo>
#include <QSettings>

Jan Möbius's avatar
Jan Möbius committed
62
#include <fstream>
Jan Möbius's avatar
Jan Möbius committed
63
64
65
66
67
68

#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
#include <OpenFlipper/common/GlobalOptions.hh>

#include <OpenMesh/Core/IO/IOManager.hh>

69

Jan Möbius's avatar
Jan Möbius committed
70
71
//== CONSTANTS ===================================================

72

Jan Möbius's avatar
Jan Möbius committed
73
// constants of color range drop down box
74
static const int COLORRANGE_0_1   = 0;
Jan Möbius's avatar
Jan Möbius committed
75
static const int COLORRANGE_0_255 = 1;
Jan Möbius's avatar
Jan Möbius committed
76

77

Jan Möbius's avatar
Jan Möbius committed
78
79
//== IMPLEMENTATION ==============================================

Jan Möbius's avatar
Jan Möbius committed
80

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
FilePTSPlugin::FilePTSPlugin() : 
  loadOptions_( 0 ), 
  saveOptions_( 0 ), 
  loadBinaryFile_   ( 0 ), 
  loadNormals_      ( 0 ), 
  loadPointsizes_   ( 0 ), 
  loadColors_       ( 0 ), 
  loadColorRange_   ( 0 ), 
  loadIndices_      ( 0 ), 
  saveBinaryFile_( 0 ), 
  saveNormals_   ( 0 ), 
  savePointsizes_( 0 ), 
  saveColors_    ( 0 ), 
  saveColorRange_( 0 ), 
  saveIndices_   ( 0 ), 
  loadMakeDefaultButton_( 0 ), 
  saveMakeDefaultButton_( 0 ) 
{ }
Jan Möbius's avatar
Jan Möbius committed
99

100
101

//----------------------------------------------------------------
Jan Möbius's avatar
Jan Möbius committed
102
103


104
bool FilePTSPlugin::readBinaryFile( const char *_filename, SplatCloud &_splatCloud ) /*const*/
Jan Möbius's avatar
Jan Möbius committed
105
{
106
107
108
  // clear splatcloud
  _splatCloud.clear();

Jan Möbius's avatar
Jan Möbius committed
109
  // set default options
110
  bool loadNormals    = true;
Jan Möbius's avatar
Jan Möbius committed
111
  bool loadPointsizes = false;
112
  bool loadColors     = false;
113
//int  loadColorRange = 0;
114
  bool loadIndices    = false;
Jan Möbius's avatar
Jan Möbius committed
115

116
117
118
119
  // get options
  if( OpenFlipper::Options::gui() && loadOptions_ )
  {
    loadNormals    = loadNormals_->   isChecked();
Jan Möbius's avatar
Jan Möbius committed
120
    loadPointsizes = loadPointsizes_->isChecked();
121
    loadColors     = loadColors_->    isChecked();
122
//  loadColorRange = loadColorRange_->currentIndex();
123
    loadIndices    = loadIndices_->   isChecked();
Jan Möbius's avatar
Jan Möbius committed
124
125
  }

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  // request properties
  bool success = true;
                       { if( !_splatCloud.requestPositions()  ) success = false; }
  if( loadNormals    ) { if( !_splatCloud.requestNormals()    ) success = false; }
  if( loadPointsizes ) { if( !_splatCloud.requestPointsizes() ) success = false; }
  if( loadColors     ) { if( !_splatCloud.requestColors()     ) success = false; }
  if( loadIndices    ) { if( !_splatCloud.requestIndices()    ) success = false; }

  // check success of requests
  if( !success )
  {
    emit log( LOGERR, QString( "Out of memory for input file \"" ) + _filename + QString( "\"\n." ) );
    return false; // return failure
  }

  // open file
  FILE *file = fopen( _filename, "rb" );
  if( !file )
  {
    emit log( LOGERR, QString( "Could not open input file \"" ) + _filename + QString( "\"\n." ) );
    return false;
  }

Jan Möbius's avatar
Jan Möbius committed
149
  // read file type
150
151
  int fileType = 0;
  fread( &fileType, sizeof(int), 1, file );
Jan Möbius's avatar
Jan Möbius committed
152
153

  // check file type
154
155
156
157
  if( fileType != 1 && fileType != 2 )
  {
    emit log( LOGERR, QString( "Bad filetype (" ) + QString::number( fileType ) + QString( ") in input file \"" ) + _filename + QString( "\"\n." ) );
    fclose( file );
Jan Möbius's avatar
Jan Möbius committed
158
    return false; // return failure
159
  }
Jan Möbius's avatar
Jan Möbius committed
160

161
162
163
  // read number of splats
  unsigned int numSplats = 0;
  fread( &numSplats, sizeof(unsigned int), 1, file );
Jan Möbius's avatar
Jan Möbius committed
164

165
166
167
168
  // set number of splats
  _splatCloud.resizeSplats( numSplats );

  // read positions
Jan Möbius's avatar
Jan Möbius committed
169
170
  {
    unsigned int i;
171
    for( i=0; i<numSplats; ++i )
172
    {
173
174
      float pos[3];
      fread( pos, sizeof(float), 3, file );
Jan Möbius's avatar
Jan Möbius committed
175

176
177
178
179
      SplatCloud::Position position;
      position[0] = pos[0];
      position[1] = pos[1];
      position[2] = pos[2];
Jan Möbius's avatar
Jan Möbius committed
180

181
      _splatCloud.positions( i ) = position;
Jan Möbius's avatar
Jan Möbius committed
182
183
184
185
    }
  }

  // read normals
186
187
  if( loadNormals )
  {
Jan Möbius's avatar
Jan Möbius committed
188
    unsigned int i;
189
    for( i=0; i<numSplats; ++i )
190
    {
Jan Möbius's avatar
Jan Möbius committed
191
      float nrm[3];
192
      fread( nrm, sizeof(float), 3, file );
Jan Möbius's avatar
Jan Möbius committed
193
194
195
196
197
198

      SplatCloud::Normal normal;
      normal[0] = nrm[0];
      normal[1] = nrm[1];
      normal[2] = nrm[2];

199
      _splatCloud.normals( i ) = normal;
Jan Möbius's avatar
Jan Möbius committed
200
201
202
203
    }
  }

  // read pointsizes
204
205
  if( loadPointsizes )
  {
Jan Möbius's avatar
Jan Möbius committed
206
    unsigned int i;
207
    for( i=0; i<numSplats; ++i )
208
209
210
    {
      float ps = 0.0f;
      fread( &ps, sizeof(float), 1, file );
Jan Möbius's avatar
Jan Möbius committed
211
212
213
214

      SplatCloud::Pointsize pointsize;
      pointsize = ps;

215
      _splatCloud.pointsizes( i ) = pointsize;
Jan Möbius's avatar
Jan Möbius committed
216
217
218
219
    }
  }

  // read colors
220
221
  if( loadColors )
  {
Jan Möbius's avatar
Jan Möbius committed
222
    unsigned int i;
223
    for( i=0; i<numSplats; ++i )
224
225
226
    {
      unsigned int col = 0;
      fread( &col, sizeof(unsigned int), 1, file );
Jan Möbius's avatar
Jan Möbius committed
227
228
229

      SplatCloud::Color color; // ignore colorrange
      color[0] = (unsigned char) ((col >> 16) & 0xFF);
230
231
      color[1] = (unsigned char) ((col >>  8) & 0xFF);
      color[2] = (unsigned char) ((col      ) & 0xFF);
Jan Möbius's avatar
Jan Möbius committed
232

233
      _splatCloud.colors( i ) = color;
Jan Möbius's avatar
Jan Möbius committed
234
235
236
    }
  }

237
  // read indices
238
239
  if( loadIndices )
  {
240
    unsigned int i;
241
    for( i=0; i<numSplats; ++i )
242
243
244
    {
      int idx = -1;
      fread( &idx, sizeof(idx), 1, file );
245
246
247
248

      SplatCloud::Index index;
      index = idx;

249
      _splatCloud.indices( i ) = index;
250
251
252
    }
  }

253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
  // check for errors
  if( ferror( file ) )
  {
    emit log( LOGERR, QString( "Could not read input file \"" ) + _filename + QString( "\"\n." ) );
    fclose( file );
    return false; // return failure
  }
  if( feof( file ) )
  {
    emit log( LOGERR, QString( "Unexpected end in input file \"" ) + _filename + QString( "\"\n." ) );
    fclose( file );
    return false; // return failure
  }

  // close file
  fclose( file );

Jan Möbius's avatar
Jan Möbius committed
270
271
  // return success
  return true;
Jan Möbius's avatar
Jan Möbius committed
272
273
}

274

Jan Möbius's avatar
Jan Möbius committed
275
276
//----------------------------------------------------------------

277
278

bool FilePTSPlugin::readTextFile( const char *_filename, SplatCloud &_splatCloud ) /*const*/
Jan Möbius's avatar
Jan Möbius committed
279
{
280
281
282
  // clear splatcloud
  _splatCloud.clear();

Jan Möbius's avatar
Jan Möbius committed
283
  // set default options
284
  bool loadNormals    = true;
Jan Möbius's avatar
Jan Möbius committed
285
  bool loadPointsizes = false;
286
287
288
  bool loadColors     = false;
  int  loadColorRange = 0;
  bool loadIndices    = false;
Jan Möbius's avatar
Jan Möbius committed
289
290

  // get options
291
292
293
  if( OpenFlipper::Options::gui() && loadOptions_ )
  {
    loadNormals    = loadNormals_   ->isChecked();
Jan Möbius's avatar
Jan Möbius committed
294
    loadPointsizes = loadPointsizes_->isChecked();
295
    loadColors     = loadColors_    ->isChecked();
Jan Möbius's avatar
Jan Möbius committed
296
    loadColorRange = loadColorRange_->currentIndex();
297
    loadIndices    = loadIndices_   ->isChecked();
Jan Möbius's avatar
Jan Möbius committed
298
299
  }

300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  // request properties
  bool success = true;
                       { if( !_splatCloud.requestPositions()  ) success = false; }
  if( loadNormals    ) { if( !_splatCloud.requestNormals()    ) success = false; }
  if( loadPointsizes ) { if( !_splatCloud.requestPointsizes() ) success = false; }
  if( loadColors     ) { if( !_splatCloud.requestColors()     ) success = false; }
  if( loadIndices    ) { if( !_splatCloud.requestIndices()    ) success = false; }

  // check success of requests
  if( !success )
  {
    emit log( LOGERR, QString( "Out of memory for input file \"" ) + _filename + QString( "\"\n." ) );
    return false; // return failure
  }

  // open file
  FILE *file = fopen( _filename, "rb" );
  if( !file )
318
  {
319
320
321
322
323
324
325
326
    emit log( LOGERR, QString( "Could not open input file \"" ) + _filename + QString( "\"\n." ) );
    return false;
  }

  int splatIdx;
  for( splatIdx = 0; ; ++splatIdx )
  {
    // read position
Jan Möbius's avatar
Jan Möbius committed
327
    {
328
329
      float pos[3];
      if( fscanf( file, "%32f %32f %32f", &pos[0], &pos[1], &pos[2] ) != 3 )
330
        break;
Jan Möbius's avatar
Jan Möbius committed
331

332
333
      // increase number of splats
      _splatCloud.pushbackSplat();
Jan Möbius's avatar
Jan Möbius committed
334

335
336
337
338
339
340
      SplatCloud::Position position;
      position[0] = pos[0];
      position[1] = pos[1];
      position[2] = pos[2];

      _splatCloud.positions( splatIdx ) = position;
Jan Möbius's avatar
Jan Möbius committed
341
342
343
    }

    // read color
344
345
    if( loadColors )
    {
Jan Möbius's avatar
Jan Möbius committed
346
      float col[3];
Jan Möbius's avatar
Jan Möbius committed
347
      fscanf( file, "%32f %32f %32f", &col[0], &col[1], &col[2] );
Jan Möbius's avatar
Jan Möbius committed
348
349
350

      SplatCloud::Color color;

351
352
      if( loadColorRange == COLORRANGE_0_1 )
      {
Jan Möbius's avatar
Jan Möbius committed
353
354
355
        color[0] = (unsigned char) (255.999f * col[0]);
        color[1] = (unsigned char) (255.999f * col[1]);
        color[2] = (unsigned char) (255.999f * col[2]);
356
357
      }
      else // loadColorRange == COLORRANGE_0_255
Jan Möbius's avatar
Jan Möbius committed
358
359
360
361
362
363
      {
        color[0] = (unsigned char) col[0];
        color[1] = (unsigned char) col[1];
        color[2] = (unsigned char) col[2];
      }

364
      _splatCloud.colors( splatIdx ) = color;
Jan Möbius's avatar
Jan Möbius committed
365
366
367
    }

    // read normal
368
369
    if( loadNormals )
    {
Jan Möbius's avatar
Jan Möbius committed
370
      float nrm[3];
Jan Möbius's avatar
Jan Möbius committed
371
      fscanf( file, "%32f %32f %32f", &nrm[0], &nrm[1], &nrm[2] );
Jan Möbius's avatar
Jan Möbius committed
372
373
374
375
376
377

      SplatCloud::Normal normal;
      normal[0] = nrm[0];
      normal[1] = nrm[1];
      normal[2] = nrm[2];

378
      _splatCloud.normals( splatIdx ) = normal;
Jan Möbius's avatar
Jan Möbius committed
379
380
381
    }

    // read pointsize
382
383
384
    if( loadPointsizes )
    {
      float ps = 0.0f;
Jan Möbius's avatar
Jan Möbius committed
385
      fscanf( file, "%32f", &ps );
Jan Möbius's avatar
Jan Möbius committed
386
387
388
389

      SplatCloud::Pointsize pointsize;
      pointsize = ps;

390
      _splatCloud.pointsizes( splatIdx ) = pointsize;
Jan Möbius's avatar
Jan Möbius committed
391
    }
392
393

    // read index
394
395
396
    if( loadIndices )
    {
      int idx = -1;
Jan Möbius's avatar
Jan Möbius committed
397
      fscanf( file, "%16i", &idx );
398
399
400
401

      SplatCloud::Index index;
      index = idx;

402
      _splatCloud.indices( splatIdx ) = index;
403
404
405
406
407
408
409
410
411
412
413
414
415
416
    }

    // check for errors
    if( ferror( file ) )
    {
      emit log( LOGERR, QString( "Could not read input file \"" ) + _filename + QString( "\"\n." ) );
      fclose( file );
      return false; // return failure
    }
    if( feof( file ) )
    {
      emit log( LOGERR, QString( "Unexpected end in input file \"" ) + _filename + QString( "\"\n." ) );
      fclose( file );
      return false; // return failure
417
    }
Jan Möbius's avatar
Jan Möbius committed
418
419
  }

420
421
422
423
424
425
426
427
428
429
430
  // check for errors
  if( !feof( file ) ) // if end-of-file is *not* reached, something went wrong
  {
    emit log( LOGERR, QString( "Bad file format of input file \"" ) + _filename + QString( "\"\n." ) );
    fclose( file );
    return false; // return failure
  }

  // close file
  fclose( file );

Jan Möbius's avatar
Jan Möbius committed
431
432
  // return success
  return true;
Jan Möbius's avatar
Jan Möbius committed
433
434
}

435

Jan Möbius's avatar
Jan Möbius committed
436
437
//----------------------------------------------------------------

438
439

bool FilePTSPlugin::writeBinaryFile( const char *_filename, const SplatCloudNode *_splatCloudNode ) /*const*/
Jan Möbius's avatar
Jan Möbius committed
440
{
Jan Möbius's avatar
Jan Möbius committed
441
  // set default options
442
  bool saveNormals    = true;
Jan Möbius's avatar
Jan Möbius committed
443
  bool savePointsizes = false;
444
  bool saveColors     = false;
445
//int  saveColorRange = 0;
446
  bool saveIndices    = false;
447

Jan Möbius's avatar
Jan Möbius committed
448
  // get options
449
450
451
  if( OpenFlipper::Options::gui() && saveOptions_ )
  {
    saveNormals    = saveNormals_->   isChecked();
Jan Möbius's avatar
Jan Möbius committed
452
    savePointsizes = savePointsizes_->isChecked();
453
    saveColors     = saveColors_->    isChecked();
454
//  saveColorRange = saveColorRange_->currentIndex();
455
    saveIndices    = saveIndices_->   isChecked();
Jan Möbius's avatar
Jan Möbius committed
456
457
  }

458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
  // use default values instead of returning a failure

//// check availability
//if( (                  !_splatCloudNode->splatCloud().hasPositions() ) ||
//    (saveNormals    && !_splatCloudNode->splatCloud().hasNormals())  ) ||
//    (savePointsizes && !_splatCloudNode->splatCloud().hasPointsizes()) ||
//    (saveColors     && !_splatCloudNode->splatCloud().hasColors()    ) ||
//    (saveIndices    && !_splatCloudNode->splatCloud().hasIndices()   )
//{
//  emit log( LOGERR, QString( "Desired properties not available for output file \"" ) + _filename + QString( "\"\n." ) );
//  return false; // return failure
//}

  // open file
  FILE *file = fopen( _filename, "wb" );
  if( !file )
  {
    emit log( LOGERR, QString( "Could not open output file \"" ) + _filename + QString( "\"\n." ) );
    return false;
  }

Jan Möbius's avatar
Jan Möbius committed
479
480
  // write file type
  int fileType = 1;
481
  fwrite( &fileType, sizeof(int), 1, file );
Jan Möbius's avatar
Jan Möbius committed
482

483
484
485
  // write number of splats
  unsigned int numSplats = _splatCloudNode->splatCloud().numSplats();
  fwrite( &numSplats, sizeof(unsigned int), 1, file );
Jan Möbius's avatar
Jan Möbius committed
486

487
  // write positions
Jan Möbius's avatar
Jan Möbius committed
488
489
  {
    unsigned int i;
490
    for( i=0; i<numSplats; ++i )
491
    {
492
      const SplatCloud::Position &position = _splatCloudNode->getPosition( i );
Jan Möbius's avatar
Jan Möbius committed
493

494
495
496
497
      float pos[3];
      pos[0] = position[0];
      pos[1] = position[1];
      pos[2] = position[2];
Jan Möbius's avatar
Jan Möbius committed
498

499
      fwrite( pos, sizeof(float), 3, file );
Jan Möbius's avatar
Jan Möbius committed
500
501
502
503
    }
  }

  // write normals
504
505
  if( saveNormals )
  {
Jan Möbius's avatar
Jan Möbius committed
506
    unsigned int i;
507
    for( i=0; i<numSplats; ++i )
508
509
    {
      const SplatCloud::Normal &normal = _splatCloudNode->getNormal( i );
Jan Möbius's avatar
Jan Möbius committed
510
511
512
513
514
515

      float nrm[3];
      nrm[0] = normal[0];
      nrm[1] = normal[1];
      nrm[2] = normal[2];

516
      fwrite( nrm, sizeof(float), 3, file );
Jan Möbius's avatar
Jan Möbius committed
517
518
519
520
    }
  }

  // write pointsizes
521
522
  if( savePointsizes )
  {
Jan Möbius's avatar
Jan Möbius committed
523
    unsigned int i;
524
    for( i=0; i<numSplats; ++i )
525
526
    {
      const SplatCloud::Pointsize &pointsize = _splatCloudNode->getPointsize( i );
Jan Möbius's avatar
Jan Möbius committed
527
528

      float ps;
529
      ps = pointsize;
Jan Möbius's avatar
Jan Möbius committed
530

531
      fwrite( &ps, sizeof(float), 1, file );
Jan Möbius's avatar
Jan Möbius committed
532
533
534
535
    }
  }

  // write colors
536
537
  if( saveColors )
  {
Jan Möbius's avatar
Jan Möbius committed
538
    unsigned int i;
539
    for( i=0; i<numSplats; ++i )
540
541
    {
      const SplatCloud::Color &color = _splatCloudNode->getColor( i );
Jan Möbius's avatar
Jan Möbius committed
542
543
544
545

      unsigned int col; // ignore colorrange
      col = (0xFF << 24) | (color[0] << 16) | (color[1] << 8) | (color[2]);

546
      fwrite( &col, sizeof(unsigned int), 1, file );
Jan Möbius's avatar
Jan Möbius committed
547
548
549
    }
  }

550
  // write indices
551
552
  if( saveIndices )
  {
553
    unsigned int i;
554
    for( i=0; i<numSplats; ++i )
555
556
    {
      const SplatCloud::Index &index = _splatCloudNode->getIndex( i );
557
558
559
560

      int idx;
      idx = index;

561
      fwrite( &idx, sizeof(int), 1, file );
562
563
564
    }
  }

565
566
567
568
569
570
571
572
573
574
575
  // check for errors
  if( ferror( file ) )
  {
    emit log( LOGERR, QString( "Could not write output file \"" ) + _filename + QString( "\"\n." ) );
    fclose( file );
    return false; // return failure
  }

  // close file
  fclose( file );

Jan Möbius's avatar
Jan Möbius committed
576
577
  // return success
  return true;
Jan Möbius's avatar
Jan Möbius committed
578
579
}

580

Jan Möbius's avatar
Jan Möbius committed
581
582
//----------------------------------------------------------------

583
584

bool FilePTSPlugin::writeTextFile( const char *_filename, const SplatCloudNode *_splatCloudNode ) /*const*/
Jan Möbius's avatar
Jan Möbius committed
585
{
Jan Möbius's avatar
Jan Möbius committed
586
  // set default options
587
  bool saveNormals    = true;
Jan Möbius's avatar
Jan Möbius committed
588
  bool savePointsizes = false;
589
590
591
  bool saveColors     = false;
  int  saveColorRange = 0;
  bool saveIndices    = false;
Jan Möbius's avatar
Jan Möbius committed
592
593

  // get options
594
595
596
  if( OpenFlipper::Options::gui() && saveOptions_ )
  {
    saveNormals    = saveNormals_->   isChecked();
Jan Möbius's avatar
Jan Möbius committed
597
    savePointsizes = savePointsizes_->isChecked();
598
    saveColors     = saveColors_->    isChecked();
Jan Möbius's avatar
Jan Möbius committed
599
    saveColorRange = saveColorRange_->currentIndex();
600
    saveIndices    = saveIndices_->   isChecked();
Jan Möbius's avatar
Jan Möbius committed
601
602
  }

603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
  // use default values instead of returning a failure

//// check availability
//if( (                  !_splatCloudNode->splatCloud().hasPositions() ) ||
//    (saveNormals    && !_splatCloudNode->splatCloud().hasNormals())  ) ||
//    (savePointsizes && !_splatCloudNode->splatCloud().hasPointsizes()) ||
//    (saveColors     && !_splatCloudNode->splatCloud().hasColors()    ) ||
//    (saveIndices    && !_splatCloudNode->splatCloud().hasIndices()   )
//{
//  emit log( LOGERR, QString( "Desired properties not available for output file \"" ) + _filename + QString( "\"\n." ) );
//  return false; // return failure
//}

  // open file
  FILE *file = fopen( _filename, "wt" );
  if( !file )
  {
    emit log( LOGERR, QString( "Could not open output file \"" ) + _filename + QString( "\"\n." ) );
    return false;
  }

  // for all splats...
  unsigned int i, numSplats = _splatCloudNode->splatCloud().numSplats();
  for( i=0; i<numSplats; ++i )
627
  {
628
    // write position
Jan Möbius's avatar
Jan Möbius committed
629
    {
630
      const SplatCloud::Position &position = _splatCloudNode->getPosition( i );
Jan Möbius's avatar
Jan Möbius committed
631

632
633
634
635
      float pos[3];
      pos[0] = position[0];
      pos[1] = position[1];
      pos[2] = position[2];
Jan Möbius's avatar
Jan Möbius committed
636

637
      fprintf( file, "%.6g %.6g %.6g", pos[0], pos[1], pos[2] );
Jan Möbius's avatar
Jan Möbius committed
638
639
640
    }

    // write color
641
642
643
    if( saveColors )
    {
      const SplatCloud::Color &color = _splatCloudNode->getColor( i );
Jan Möbius's avatar
Jan Möbius committed
644

645
646
      if( saveColorRange == COLORRANGE_0_1 )
      {
Jan Möbius's avatar
Jan Möbius committed
647
648
649
650
651
652
653
        static const float RCP255 = 1.0f / 255.0f;

        float col[3];
        col[0] = RCP255 * color[0];
        col[1] = RCP255 * color[1];
        col[2] = RCP255 * color[2];

654
655
656
        fprintf( file, " %.6g %.6g %.6g", col[0], col[1], col[2] );
      }
      else // saveColorRange == COLORRANGE_0_255
Jan Möbius's avatar
Jan Möbius committed
657
658
659
660
661
662
      {
        int col[3]; // use int, *not* unsigned char !
        col[0] = color[0];
        col[1] = color[1];
        col[2] = color[2];

663
        fprintf( file, " %i %i %i", col[0], col[1], col[2] );
Jan Möbius's avatar
Jan Möbius committed
664
665
666
667
      }
    }

    // write normal
668
669
670
    if( saveNormals )
    {
      const SplatCloud::Normal &normal = _splatCloudNode->getNormal( i );
Jan Möbius's avatar
Jan Möbius committed
671
672
673
674
675
676

      float nrm[3];
      nrm[0] = normal[0];
      nrm[1] = normal[1];
      nrm[2] = normal[2];

677
      fprintf( file, " %.6g %.6g %.6g", nrm[0], nrm[1], nrm[2] );
Jan Möbius's avatar
Jan Möbius committed
678
679
680
    }

    // write pointsize
681
682
683
    if( savePointsizes )
    {
      const SplatCloud::Pointsize &pointsize = _splatCloudNode->getPointsize( i );
Jan Möbius's avatar
Jan Möbius committed
684
685

      float ps;
686
      ps = pointsize;
Jan Möbius's avatar
Jan Möbius committed
687

688
      fprintf( file, " %.6g", ps );
Jan Möbius's avatar
Jan Möbius committed
689
690
    }

691
    // write index
692
693
694
    if( saveIndices )
    {
      const SplatCloud::Index &index = _splatCloudNode->getIndex( i );
695
696
697
698

      int idx;
      idx = index;

699
      fprintf( file, " %i", idx );
700
701
    }

702
703
704
705
706
707
708
709
710
    fprintf( file, "\n" );
  }

  // check for errors
  if( ferror( file ) )
  {
    emit log( LOGERR, QString( "Could not write output file \"" ) + _filename + QString( "\"\n." ) );
    fclose( file );
    return false; // return failure
Jan Möbius's avatar
Jan Möbius committed
711
712
  }

713
714
715
  // close file
  fclose( file );

Jan Möbius's avatar
Jan Möbius committed
716
717
  // return success
  return true;
Jan Möbius's avatar
Jan Möbius committed
718
719
}

720

Jan Möbius's avatar
Jan Möbius committed
721
722
//----------------------------------------------------------------

723
724

int FilePTSPlugin::loadObject( QString _filename )
Jan Möbius's avatar
Jan Möbius committed
725
{
Jan Möbius's avatar
Jan Möbius committed
726
  // set default options
727
  bool loadBinaryFile = false;
Jan Möbius's avatar
Jan Möbius committed
728
729

  // get options
730
731
  if( OpenFlipper::Options::gui() && loadOptions_ )
  {
732
    loadBinaryFile = loadBinaryFile_->   isChecked();
Jan Möbius's avatar
Jan Möbius committed
733
734
735
736
  }

  // add a new, empty splatcloud object
  int id = -1;
737
738
739
740
741
  emit addEmptyObject( DATA_SPLATCLOUD, id );

  // check id
  if( id == -1 )
    return -1; // return failure
Jan Möbius's avatar
Jan Möbius committed
742
743
744

  // get splatcloud-object by id
  SplatCloudObject *splatCloudObject = 0;
745
746
747
748
749
  if( !PluginFunctions::getObject( id, splatCloudObject ) )
  {
    emit deleteObject( id );
    return -1; // return failure
  }
Jan Möbius's avatar
Jan Möbius committed
750
751

  // check if splatcloud-object is okay
752
753
754
755
756
  if( !splatCloudObject )
  {
    emit deleteObject( id );
    return -1; // return failure
  }
Jan Möbius's avatar
Jan Möbius committed
757

758
759
760
761
  // set name of splatcloud-object to filename
  splatCloudObject->setFromFileName( _filename );
  splatCloudObject->setName( splatCloudObject->filename() );

762
763
  // get splatcloud and scenegraph splatcloud-node
  SplatCloud     *splatCloud     = splatCloudObject->splatCloud();
Jan Möbius's avatar
Jan Möbius committed
764
765
766
  SplatCloudNode *splatCloudNode = splatCloudObject->splatCloudNode();

  // check if splatcloud-node if okay
767
  if( !splatCloud || !splatCloudNode )
768
769
770
771
  {
    emit deleteObject( id );
    return -1; // return failure
  }
Jan Möbius's avatar
Jan Möbius committed
772
773

  // read file
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
  if( loadBinaryFile )
  {
    if( !readBinaryFile( _filename.toLatin1(), *splatCloud ) )
    {
      emit deleteObject( id );
      return -1; // return failure
    }
  }
  else
  {
    if( !readTextFile( _filename.toLatin1(), *splatCloud ) )
    {
      emit deleteObject( id );
      return -1; // return failure
    }
Jan Möbius's avatar
Jan Möbius committed
789
790
791
  }

  // emit signals that the object has to be updated and that a file was opened
792
793
  emit updatedObject( splatCloudObject->id(), UPDATE_ALL);
  emit openedFile   ( splatCloudObject->id()            );
Jan Möbius's avatar
Jan Möbius committed
794
795

  // get drawmodes
796
797
798
  ACG::SceneGraph::DrawModes::DrawMode splatsDrawMode = ACG::SceneGraph::DrawModes::getDrawMode( "Splats" );
  ACG::SceneGraph::DrawModes::DrawMode dotsDrawMode   = ACG::SceneGraph::DrawModes::getDrawMode( "Dots"   );
  ACG::SceneGraph::DrawModes::DrawMode pointsDrawMode = ACG::SceneGraph::DrawModes::getDrawMode( "Points" );
Jan Möbius's avatar
Jan Möbius committed
799
800

  // if drawmodes don't exist something went wrong
801
802
803
804
805
806
807
808
  if( splatsDrawMode == ACG::SceneGraph::DrawModes::NONE || 
      dotsDrawMode   == ACG::SceneGraph::DrawModes::NONE || 
      pointsDrawMode == ACG::SceneGraph::DrawModes::NONE )
  {
    emit log( LOGERR, tr("Shader DrawModes for SplatCloud not existent!") );
  }
  else
  {
Jan Möbius's avatar
Jan Möbius committed
809
810
811
812
    // get global drawmode
    ACG::SceneGraph::DrawModes::DrawMode drawmode = PluginFunctions::drawMode();

    // if global drawmode does *not* contain any of 'Splats', 'Dots' or 'Points' drawmode, add 'Points'
813
814
815
816
    if( !drawmode.containsAtomicDrawMode( splatsDrawMode ) && 
        !drawmode.containsAtomicDrawMode( dotsDrawMode   ) && 
        !drawmode.containsAtomicDrawMode( pointsDrawMode ) )
    {
Jan Möbius's avatar
Jan Möbius committed
817
      drawmode |= pointsDrawMode;
818
      PluginFunctions::setDrawMode( drawmode );
Jan Möbius's avatar
Jan Möbius committed
819
820
821
822
823
    }
  }

  // return the id of the new splatcloud object
  return id;
Jan Möbius's avatar
Jan Möbius committed
824
825
}

826

Jan Möbius's avatar
Jan Möbius committed
827
828
//----------------------------------------------------------------

829

830
bool FilePTSPlugin::saveObject( int _objectId, QString _filename )
Jan Möbius's avatar
Jan Möbius committed
831
{
Jan Möbius's avatar
Jan Möbius committed
832
  // set default options
Jan Möbius's avatar
Jan Möbius committed
833
  bool saveBinaryFile = false;
Jan Möbius's avatar
Jan Möbius committed
834
835

  // get options
836
837
  if( OpenFlipper::Options::gui() && saveOptions_ )
  {
Jan Möbius's avatar
Jan Möbius committed
838
839
840
841
842
    saveBinaryFile = saveBinaryFile_->isChecked();
  }

  // get splatcloud-object by id
  SplatCloudObject *splatCloudObject = 0;
843
  if( !PluginFunctions::getObject( _objectId, splatCloudObject ) )
844
    return false; // return failure
Jan Möbius's avatar
Jan Möbius committed
845
846

  // check if splatcloud-object is okay
847
848
  if( !splatCloudObject )
    return false; // return failure
Jan Möbius's avatar
Jan Möbius committed
849

850
851
852
853
  // change name of splatcloud-object to filename
  splatCloudObject->setFromFileName( _filename );
  splatCloudObject->setName( splatCloudObject->filename() );

Jan Möbius's avatar
Jan Möbius committed
854
855
856
857
  // get scenegraph splatcloud-node
  const SplatCloudNode *splatCloudNode = splatCloudObject->splatCloudNode();

  // check if splatcloud-node if okay
858
  if( !splatCloudNode )
859
    return false; // return failure
Jan Möbius's avatar
Jan Möbius committed
860
861

  // write file
862
863
864
865
866
867
868
869
870
  if( saveBinaryFile )
  {
    if( !writeBinaryFile( _filename.toLatin1(), splatCloudNode ) )
      return false; // return failure
  }
  else
  {
    if( !writeTextFile( _filename.toLatin1(), splatCloudNode ) )
      return false; // return failure
Jan Möbius's avatar
Jan Möbius committed
871
872
873
874
  }

  // return success
  return true;
Jan Möbius's avatar
Jan Möbius committed
875
876
}

877

Jan Möbius's avatar
Jan Möbius committed
878
879
//----------------------------------------------------------------

880
881

QWidget *FilePTSPlugin::loadOptionsWidget( QString /*_currentFilter*/ )
Jan Möbius's avatar
Jan Möbius committed
882
{
883
884
  if( loadOptions_ == 0 )
  {
Jan Möbius's avatar
Jan Möbius committed
885
886
    // create new widget (including Load Options and buttons)

887
    loadBinaryFile_ = new QCheckBox( "Load as Binary File" );
Jan Möbius's avatar
Jan Möbius committed
888

889
890
891
    loadNormals_    = new QCheckBox( "Contains Normals"    );
    loadPointsizes_ = new QCheckBox( "Contains Pointsizes" );
    loadColors_     = new QCheckBox( "Contains Colors"     );
Jan Möbius's avatar
Jan Möbius committed
892
893

    loadColorRange_ = new QComboBox();
894
895
    loadColorRange_->addItem( "[0..1]"   );
    loadColorRange_->addItem( "[0..255]" );
Jan Möbius's avatar
Jan Möbius committed
896
897
898
    slotUpdateLoadColorRange();

    QHBoxLayout *loadColorsLayout = new QHBoxLayout();
899
900
901
    loadColorsLayout->setSpacing( 6 );
    loadColorsLayout->addWidget( loadColors_     );
    loadColorsLayout->addWidget( loadColorRange_ );
Jan Möbius's avatar
Jan Möbius committed
902

903
904
    loadIndices_ = new QCheckBox( "Contains Indices" );

Jan Möbius's avatar
Jan Möbius committed
905
    QVBoxLayout *loadStructureLayout = new QVBoxLayout();
906
    loadStructureLayout->setSpacing( 6 );
907
908
909
910
    loadStructureLayout->addWidget( loadNormals_     );
    loadStructureLayout->addWidget( loadPointsizes_  );
    loadStructureLayout->addItem  ( loadColorsLayout );
    loadStructureLayout->addWidget( loadIndices_     );
Jan Möbius's avatar
Jan Möbius committed
911

912
913
    QGroupBox *loadStructureGroupBox = new QGroupBox( "Internal File Structure" );
    loadStructureGroupBox->setLayout( loadStructureLayout );
Jan Möbius's avatar
Jan Möbius committed
914

915
    loadMakeDefaultButton_ = new QPushButton( "Make Default" );
Jan Möbius's avatar
Jan Möbius committed
916
917

    QVBoxLayout *loadLayout = new QVBoxLayout();
918
919
920
921
922
    loadLayout->setAlignment( Qt::AlignTop );
    loadLayout->setSpacing( 6 );
    loadLayout->addWidget( loadBinaryFile_        );
    loadLayout->addWidget( loadStructureGroupBox  );
    loadLayout->addWidget( loadMakeDefaultButton_ );
Jan Möbius's avatar
Jan Möbius committed
923
924

    loadOptions_ = new QWidget();
925
    loadOptions_->setLayout( loadLayout );
Jan Möbius's avatar
Jan Möbius committed
926
927

    // connect events to slots
928
929
930
    connect( loadBinaryFile_,        SIGNAL( stateChanged(int) ), this, SLOT( slotUpdateLoadColorRange()         ) );
    connect( loadColors_,            SIGNAL( stateChanged(int) ), this, SLOT( slotUpdateLoadColorRange()         ) );
    connect( loadMakeDefaultButton_, SIGNAL( clicked()         ), this, SLOT( slotLoadMakeDefaultButtonClicked() ) );
Jan Möbius's avatar
Jan Möbius committed
931
932

    // get Load Options from OpenFlipper (from disc)
933
934
935
936
937
938
    loadBinaryFile_->   setChecked     ( OpenFlipperSettings().value( "FilePTS/Load/BinaryFile", true ).toBool() );
    loadNormals_->      setChecked     ( OpenFlipperSettings().value( "FilePTS/Load/Normals",    true ).toBool() );
    loadPointsizes_->   setChecked     ( OpenFlipperSettings().value( "FilePTS/Load/Pointsizes", true ).toBool() );
    loadColors_->       setChecked     ( OpenFlipperSettings().value( "FilePTS/Load/Colors",     true ).toBool() );
    loadColorRange_->   setCurrentIndex( OpenFlipperSettings().value( "FilePTS/Load/ColorRange",    0 ).toInt()  );
    loadIndices_->      setChecked     ( OpenFlipperSettings().value( "FilePTS/Load/Indices",    true ).toBool() );
Jan Möbius's avatar
Jan Möbius committed
939
940
941
  }

  return loadOptions_;
Jan Möbius's avatar
Jan Möbius committed
942
943
}

944

Jan Möbius's avatar
Jan Möbius committed
945
946
//----------------------------------------------------------------

947
948

QWidget *FilePTSPlugin::saveOptionsWidget( QString _currentFilter )
Jan Möbius's avatar
Jan Möbius committed
949
{
950
951
  if( saveOptions_ == 0 )
  {
Jan Möbius's avatar
Jan Möbius committed
952
953
    // create new widget (including Save Options and buttons)

954
    saveBinaryFile_ = new QCheckBox( "Save as Binary File" );
Jan Möbius's avatar
Jan Möbius committed
955

956
957
958
    saveNormals_    = new QCheckBox( "Save Normals"        );
    savePointsizes_ = new QCheckBox( "Save Pointsizes"     );
    saveColors_     = new QCheckBox( "Save Colors"         );
Jan Möbius's avatar
Jan Möbius committed
959
960

    saveColorRange_ = new QComboBox();
961
962
    saveColorRange_->addItem( "[0..1]"   );
    saveColorRange_->addItem( "[0..255]" );
Jan Möbius's avatar
Jan Möbius committed
963
964
965
    slotUpdateSaveColorRange();

    QHBoxLayout *saveColorsLayout = new QHBoxLayout();
966
967
968
    saveColorsLayout->setSpacing( 6 );
    saveColorsLayout->addWidget( saveColors_     );
    saveColorsLayout->addWidget( saveColorRange_ );
Jan Möbius's avatar
Jan Möbius committed
969

970
971
    saveIndices_ = new QCheckBox( "Save Indices" );

Jan Möbius's avatar
Jan Möbius committed
972
    QVBoxLayout *saveStructureLayout = new QVBoxLayout();
973
    saveStructureLayout->setSpacing( 6 );
974
975
976
977
    saveStructureLayout->addWidget( saveNormals_     );
    saveStructureLayout->addWidget( savePointsizes_  );
    saveStructureLayout->addItem  ( saveColorsLayout );
    saveStructureLayout->addWidget( saveIndices_     );
Jan Möbius's avatar
Jan Möbius committed
978

979
980
    QGroupBox *saveStructureGroupBox = new QGroupBox( "Internal File Structure" );
    saveStructureGroupBox->setLayout( saveStructureLayout );
Jan Möbius's avatar
Jan Möbius committed
981

982
    saveMakeDefaultButton_ = new QPushButton( "Make Default" );
Jan Möbius's avatar
Jan Möbius committed
983
984

    QVBoxLayout *saveLayout = new QVBoxLayout();
985
986
987
988
989
    saveLayout->setAlignment( Qt::AlignTop );
    saveLayout->setSpacing( 6 );
    saveLayout->addWidget( saveBinaryFile_        );
    saveLayout->addWidget( saveStructureGroupBox  );
    saveLayout->addWidget( saveMakeDefaultButton_ );
Jan Möbius's avatar
Jan Möbius committed
990
991

    saveOptions_ = new QWidget();
992
    saveOptions_->setLayout( saveLayout );
Jan Möbius's avatar
Jan Möbius committed
993
994

    // connect events to slots
995
996
997
    connect( saveBinaryFile_,        SIGNAL( stateChanged(int) ), this, SLOT( slotUpdateSaveColorRange()         ) );
    connect( saveColors_,            SIGNAL( stateChanged(int) ), this, SLOT( slotUpdateSaveColorRange()         ) );
    connect( saveMakeDefaultButton_, SIGNAL( clicked()         ), this, SLOT( slotSaveMakeDefaultButtonClicked() ) );
Jan Möbius's avatar
Jan Möbius committed
998
999

    // get Save Options from OpenFlipper (from disc)
1000
    saveBinaryFile_->setChecked     ( OpenFlipperSettings().value( "FilePTS/Save/BinaryFile", true ).toBool() );
1001
    saveNormals_->   setChecked     ( OpenFlipperSettings().value( "FilePTS/Save/Normals",    true ).toBool() );
1002
    savePointsizes_->setChecked     ( OpenFlipperSettings().value( "FilePTS/Save/Pointsizes", true ).toBool() );
1003
1004
1005
    saveColors_->    setChecked     ( OpenFlipperSettings().value( "FilePTS/Save/Colors",     true ).toBool() );
    saveColorRange_->setCurrentIndex( OpenFlipperSettings().value( "FilePTS/Save/ColorRange",    0 ).toInt()  );
    saveIndices_->   setChecked     ( OpenFlipperSettings().value( "FilePTS/Save/Indices",    true ).toBool() );
Jan Möbius's avatar
Jan Möbius committed
1006
1007
1008
  }

  return saveOptions_;
Jan Möbius's avatar
Jan Möbius committed
1009
1010
}

1011

Jan Möbius's avatar
Jan Möbius committed
1012
1013
//----------------------------------------------------------------

1014

Jan Möbius's avatar
Jan Möbius committed
1015
1016
void FilePTSPlugin::slotUpdateLoadColorRange()
{
1017
  loadColorRange_->setEnabled( loadColors_->isChecked() && !loadBinaryFile_->isChecked() );
Jan Möbius's avatar
Jan Möbius committed
1018
1019
}

1020

Jan Möbius's avatar
Jan Möbius committed
1021
1022
//----------------------------------------------------------------

1023

Jan Möbius's avatar
Jan Möbius committed
1024
1025
void FilePTSPlugin::slotUpdateSaveColorRange()
{
1026
  saveColorRange_->setEnabled( saveColors_->isChecked() && !saveBinaryFile_->isChecked() );
Jan Möbius's avatar
Jan Möbius committed
1027
1028
}

1029