Developer Documentation

FileBundle.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42
43
44 //================================================================
45 //
46 // CLASS FileBundlePlugin - IMPLEMENTATION
47 //
48 //================================================================
49
50
51 //== INCLUDES ====================================================
52
53
54 #include "FileBundle.hh"
55
56
57 #include <QtWidgets>
58
59 #include <fstream>
60
61 #include <OpenFlipper/BasePlugin/PluginFunctions.hh>
62 #include <OpenFlipper/common/GlobalOptions.hh>
63
64 #include <OpenMesh/Core/IO/IOManager.hh>
65
66 #include <ObjectTypes/Camera/Camera.hh>
67
68
69 //== CONSTANTS ===================================================
70
71
72 static const char IMAGELIST_SUFFIX[] = ".txt";
73 static const char IMAGELIST_FALLBACK[] = "image_list.txt";
74
75
76 //== IMPLEMENTATION ==============================================
77
78
79 static std::string readLine( FILE *_file )
80 {
81 // create empty string
82 std::string result = "";
83
84 while( true )
85 {
86 // read next char
87 char c;
88 fscanf( _file, "%c", &c );
89
90 // if end of file or line is reached, break
91 if( feof( _file ) || c == '\0' || c == '\n' || c == '\r' )
92 break;
93
94 // copy char to string
95 result += c;
96 }
97
98 // return string
99 return result;
100 }
101
102
103 //----------------------------------------------------------------
104
105
106 static void splitFilename( const std::string &_str, std::string &_path, std::string &_name, std::string &_ext )
107 {
108 size_t i = _str.find_last_of( "/\\" );
109
110 std::string rest;
111
112 if( i == std::string::npos )
113 {
114 _path = "";
115 rest = _str;
116 }
117 else
118 {
119 _path = _str.substr( 0, i+1 ); // 0 .. i
120 rest = _str.substr( i+1 ); // i+1 .. end
121 }
122
123 size_t j = rest.find_last_of( '.' );
124
125 if( j == std::string::npos )
126 {
127 _name = rest;
128 _ext = "";
129 }
130 else
131 {
132 _name = rest.substr( 0, j ); // 0 .. j-1
133 _ext = rest.substr( j ); // j .. end
134 }
135 }
136
137
138 //----------------------------------------------------------------
139
140
141 bool FileBundlePlugin::addEmptyObjects( unsigned int _num, const DataType &_dataType, std::vector<int> &_objectIDs )
142 {
143 deleteObjects( _objectIDs );
144 _objectIDs.reserve( _num );
145
146 OpenFlipper::Options::blockSceneGraphUpdates();
147
148 unsigned int i;
149 for( i=0; i<_num; ++i )
150 {
151 int objectId = -1;
152 emit addEmptyObject( _dataType, objectId );
153
154 if( objectId == -1 )
155 break;
156
157 _objectIDs.push_back( objectId );
158 }
159
160 OpenFlipper::Options::unblockSceneGraphUpdates();
161
162 if( i == _num )
163 return true;
164
165 deleteObjects( _objectIDs );
166 return false;
167 }
168
169
170 //----------------------------------------------------------------
171
172
173 void FileBundlePlugin::deleteObjects( std::vector<int> &_objectIDs )
174 {
175 unsigned int i, num = _objectIDs.size();
176 for( i=0; i<num; ++i )
177 emit deleteObject( _objectIDs[ i ] );
178
179 _objectIDs.clear();
180 }
181
182
183 //----------------------------------------------------------------
184
185
186 bool FileBundlePlugin::readImagelistFile( const char *_filename, std::vector<std::string> &_imagePaths ) /*const*/
187 {
188 _imagePaths.clear();
189
190 FILE *file = fopen( _filename, "rt" );
191 if( !file )
192 {
193 emit log( LOGINFO, tr("Could not open imagelist file \"%1\".\n").arg( _filename ) );
194 return false;
195 }
196
197 char path[4096];
198 char temp[32];
199
200 while( true )
201 {
202 fscanf( file, "%4095s", path );
203 fscanf( file, "%31s", temp );
204 fscanf( file, "%31s", temp );
205
206 if( feof( file ) )
207 break;
208
209 _imagePaths.push_back( std::string( path ) );
210 }
211
212 fclose( file );
213
214 emit log( LOGINFO, tr("Using imagelist file \"%1\".\n").arg( _filename ) );
215 return true;
216 }
217
218
219 //----------------------------------------------------------------
220
221
222 void FileBundlePlugin::readCameras( FILE *_file, const std::vector<int> &_cameraObjectIDs, SplatCloud_Cameras &_cameras ) /*const*/
223 {
224 char str[256];
225
226 unsigned int cameraIdx = 0;
227 SplatCloud_Cameras::iterator cameraIter;
228 for( cameraIter = _cameras.begin(); cameraIter != _cameras.end(); ++cameraIter, ++cameraIdx )
229 {
230 SplatCloud_Camera &camera = *cameraIter;
231
232 camera.objectId_ = _cameraObjectIDs[ cameraIdx ];
233
234 SplatCloud_Projection &proj = camera.projection_;
235 fscanf( _file, "%32s", str ); proj.f_ = atof( str );
236 fscanf( _file, "%32s", str ); proj.k1_ = atof( str );
237 fscanf( _file, "%32s", str ); proj.k2_ = atof( str );
238 fscanf( _file, "%32s", str ); proj.r_[0][0] = atof( str );
239 fscanf( _file, "%32s", str ); proj.r_[0][1] = atof( str );
240 fscanf( _file, "%32s", str ); proj.r_[0][2] = atof( str );
241 fscanf( _file, "%32s", str ); proj.r_[1][0] = atof( str );
242 fscanf( _file, "%32s", str ); proj.r_[1][1] = atof( str );
243 fscanf( _file, "%32s", str ); proj.r_[1][2] = atof( str );
244 fscanf( _file, "%32s", str ); proj.r_[2][0] = atof( str );
245 fscanf( _file, "%32s", str ); proj.r_[2][1] = atof( str );
246 fscanf( _file, "%32s", str ); proj.r_[2][2] = atof( str );
247 fscanf( _file, "%32s", str ); proj.t_[0] = atof( str );
248 fscanf( _file, "%32s", str ); proj.t_[1] = atof( str );
249 fscanf( _file, "%32s", str ); proj.t_[2] = atof( str );
250
251 camera.imagePath_ = "";
252
253 camera.imageWidth_ = 0;
254 camera.imageHeight_ = 0;
255 }
256 }
257
258
259 //----------------------------------------------------------------
260
261
262 void FileBundlePlugin::readPoints( FILE *_file, const std::vector<int> &_cameraObjectIDs, SplatCloud &_splatCloud ) /*const*/
263 {
264 char str[256];
265
266 int maxCamObjId = _cameraObjectIDs.size() - 1;
267
268 unsigned int splatIdx;
269 for( splatIdx = 0; splatIdx < _splatCloud.numSplats(); ++splatIdx )
270 {
271 {
272 SplatCloud::Position &pos = _splatCloud.positions( splatIdx );
273 fscanf( _file, "%32s", str ); pos[0] = atof( str );
274 fscanf( _file, "%32s", str ); pos[1] = atof( str );
275 fscanf( _file, "%32s", str ); pos[2] = atof( str );
276 }
277
278 {
279 SplatCloud::Color &col = _splatCloud.colors( splatIdx );
280 unsigned int r=0, g=0, b=0;
281 fscanf( _file, "%16u", &r ); col[0] = r;
282 fscanf( _file, "%16u", &g ); col[1] = g;
283 fscanf( _file, "%16u", &b ); col[2] = b;
284 }
285
286 {
287 SplatCloud::Viewlist &viewlist = _splatCloud.viewlists( splatIdx );
288
289 unsigned int numEntries = 0;
290 fscanf( _file, "%16u", &numEntries );
291
292 viewlist.resize( numEntries );
293
294 SplatCloud::Viewlist::iterator viewIter;
295 for( viewIter = viewlist.begin(); viewIter != viewlist.end(); ++viewIter )
296 {
297 int i = -1;
298 int j = -1;
299 fscanf( _file, "%16i", &i ); viewIter->cameraObjectId_ = ((i >= 0) && (i <= maxCamObjId)) ? _cameraObjectIDs[ i ] : -1;
300 fscanf( _file, "%16i", &j ); viewIter->featureIdx_ = j;
301 fscanf( _file, "%32s", str ); viewIter->x_ = atof( str );
302 fscanf( _file, "%32s", str ); viewIter->y_ = atof( str );
303 }
304 }
305 }
306 }
307
308
309 //----------------------------------------------------------------
310
311
312 bool FileBundlePlugin::readBundleFile( const char *_filename, SplatCloud &_splatCloud ) /*const*/
313 {
314 // clear splatcloud
315 _splatCloud.clear();
316
317 // open file
318 FILE *file = fopen( _filename, "rt" );
319 if( !file )
320 {
321 emit log( LOGERR, tr("Could not open input file \"%1\".\n").arg( _filename ) );
322 return false; // return failure
323 }
324
325 // read and check first line
326 std::string magicAndVersion = readLine( file );
327 if( magicAndVersion.compare( "# Bundle file v0.3" ) != 0 )
328 {
329 emit log( LOGERR, tr("Bad magic/version \"%1\" in input file \"%2\".\n").arg( magicAndVersion.c_str(), _filename ) );
330 fclose( file );
331 return false; // return failure
332 }
333
334 // read counts
335 unsigned int numCameras = 0;
336 unsigned int numPoints = 0;
337 fscanf( file, "%16u", &numCameras );
338 fscanf( file, "%16u", &numPoints );
339
340 // create camera object IDs
341 std::vector<int> cameraObjectIDs;
342 if( !addEmptyObjects( numCameras, DATA_CAMERA, cameraObjectIDs ) )
343 {
344 emit log( LOGERR, tr("Unable to add %1 cameras for input file \"%2\".\n").arg( QString::number( numCameras ), _filename ) );
345 fclose( file );
346 return false; // return failure
347 }
348
349 // read cameras data block
350 if( numCameras != 0 )
351 {
352 SplatCloud_CameraManager &cameraManager = _splatCloud.requestCloudProperty( SPLATCLOUD_CAMERAMANAGER_HANDLE )->data();
353
354 cameraManager.cameras_.resize( numCameras );
355 readCameras( file, cameraObjectIDs, cameraManager.cameras_ );
356
357 // set image paths
358 {
359 std::vector<std::string> imagePaths;
360
361 std::string path, name, ext;
362 splitFilename( _filename, path, name, ext );
363
364 if( !readImagelistFile( (path + name + IMAGELIST_SUFFIX).c_str(), imagePaths ) )
365 readImagelistFile( (path + IMAGELIST_FALLBACK ).c_str(), imagePaths );
366
367 bool hasImg = (cameraManager.cameras_.size() <= imagePaths.size());
368
369 if( hasImg )
370 {
371 unsigned int cameraIdx = 0;
372 SplatCloud_Cameras::iterator cameraIter;
373 for( cameraIter = cameraManager.cameras_.begin(); cameraIter != cameraManager.cameras_.end(); ++cameraIter, ++cameraIdx )
374 cameraIter->imagePath_ = imagePaths[ cameraIdx ];
375 }
376
377 _splatCloud.requestCloudProperty( SPLATCLOUD_GENERALMANAGER_HANDLE )->data().flags_.set( SPLATCLOUD_CAMERA_HAS_IMAGEPATH_FLAG, hasImg );
378 }
379 }
380
381 // read points data block
382 if( numPoints != 0 )
383 {
384 _splatCloud.resizeSplats( numPoints );
385 _splatCloud.requestPositions();
386 _splatCloud.requestColors();
387 _splatCloud.requestViewlists();
388 readPoints( file, cameraObjectIDs, _splatCloud );
389
390 _splatCloud.requestCloudProperty( SPLATCLOUD_GENERALMANAGER_HANDLE )->data().flags_.set( SPLATCLOUD_SPLAT_VIEWLIST_HAS_FEATURE_INDICES_FLAG, true );
391 _splatCloud.requestCloudProperty( SPLATCLOUD_GENERALMANAGER_HANDLE )->data().flags_.set( SPLATCLOUD_SPLAT_VIEWLIST_COORDS_NORMALIZED_FLAG, false );
392 }
393
394 // check if reading error occured
395 if( feof( file ) )
396 {
397 emit log( LOGERR, tr("Unexpected end in input file \"%1\".\n" ).arg( _filename ) );
398 fclose( file );
399 return false; // return failure
400 }
401
402 // close file
403 fclose( file );
404
405 // return success
406 return true;
407 }
408
409
410 //----------------------------------------------------------------
411
412
413 bool FileBundlePlugin::writeBundleFile( const char *_filename, const SplatCloud &_splatCloud ) /*const*/
414 {
415 return false;
416 }
417
418
419 //----------------------------------------------------------------
420
421
422 int FileBundlePlugin::loadObject( QString _filename )
423 {
424 // add a new, empty splatcloud-object
425 int splatCloudObjectId = -1;
426 emit addEmptyObject( DATA_SPLATCLOUD, splatCloudObjectId );
427 if( splatCloudObjectId != -1 )
428 {
429 // get splatcloud-object by id
430 SplatCloudObject *splatCloudObject = 0;
431 if( PluginFunctions::getObject( splatCloudObjectId, splatCloudObject ) )
432 {
433 // set name of splatcloud-object to filename
434 splatCloudObject->setFromFileName( _filename );
435 splatCloudObject->setName( splatCloudObject->filename() );
436
437 // get splatcloud and scenegraph splatcloud-node
438 SplatCloud *splatCloud = splatCloudObject->splatCloud();
439 SplatCloudNode *splatCloudNode = splatCloudObject->splatCloudNode();
440 if( (splatCloud != 0) && (splatCloudNode != 0) )
441 {
442 // read splatcloud from disk
443 if( readBundleFile( _filename.toLatin1(), *splatCloud ) )
444 {
445 // emit signals that the splatcloud-object has to be updated and that a file was opened
446 emit updatedObject( splatCloudObjectId, UPDATE_ALL );
447 emit openedFile( splatCloudObjectId );
448
449 // get drawmodes
450 ACG::SceneGraph::DrawModes::DrawMode splatsDrawMode = ACG::SceneGraph::DrawModes::getDrawMode( "Splats" );
451 ACG::SceneGraph::DrawModes::DrawMode dotsDrawMode = ACG::SceneGraph::DrawModes::getDrawMode( "Dots" );
452 ACG::SceneGraph::DrawModes::DrawMode pointsDrawMode = ACG::SceneGraph::DrawModes::getDrawMode( "Points" );
453
454 // if drawmodes don't exist something went wrong
455 if( splatsDrawMode == ACG::SceneGraph::DrawModes::NONE ||
456 dotsDrawMode == ACG::SceneGraph::DrawModes::NONE ||
457 pointsDrawMode == ACG::SceneGraph::DrawModes::NONE )
458 {
459 emit log( LOGERR, tr("Shader DrawModes for SplatCloud not existent!") );
460 }
461 else
462 {
463 // get global drawmode
464 ACG::SceneGraph::DrawModes::DrawMode drawmode = PluginFunctions::drawMode();
465
466 // if global drawmode does *not* contain any of 'Splats', 'Dots' or 'Points' drawmode, add 'Points'
467 if( !drawmode.containsAtomicDrawMode( splatsDrawMode ) &&
468 !drawmode.containsAtomicDrawMode( dotsDrawMode ) &&
469 !drawmode.containsAtomicDrawMode( pointsDrawMode ) )
470 {
471 drawmode |= pointsDrawMode;
472 PluginFunctions::setDrawMode( drawmode );
473 }
474 }
475
476 // return success
477 return splatCloudObjectId;
478 }
479 }
480 }
481 }
482
483 // return failure
484 return -1;
485 }
486
487
488 //----------------------------------------------------------------
489
490
491 bool FileBundlePlugin::saveObject( int _objectId, QString _filename )
492 {
493 // get splatcloud-object by id
494 SplatCloudObject *splatCloudObject = 0;
495 if( PluginFunctions::getObject( _objectId, splatCloudObject ) )
496 {
497 // change name of splatcloud-object to filename
498 splatCloudObject->setFromFileName( _filename );
499 splatCloudObject->setName( splatCloudObject->filename() );
500
501 // get splatcloud
502 SplatCloud *splatCloud = splatCloudObject->splatCloud();
503 if( splatCloud != 0 )
504 {
505 // write splatcloud to disk
506 if( writeBundleFile( _filename.toLatin1(), *splatCloud ) )
507 {
508 // return success
509 return true;
510 }
511 }
512 }
513
514 // return failure
515 return false;
516 }
517
518
519 //----------------------------------------------------------------
520
521
522 QWidget *FileBundlePlugin::saveOptionsWidget( QString /*_currentFilter*/ )
523 {
524 return 0;
525 }
526
527
528 //----------------------------------------------------------------
529
530
531 QWidget *FileBundlePlugin::loadOptionsWidget( QString /*_currentFilter*/ )
532 {
533 return 0;
534 }
535
536
537 //================================================================
538
LOGINFO
Definition: LoggingInterface.hh:94
UPDATE_ALL
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
SplatCloud::requestViewlists
bool requestViewlists()
Request the predefined property.
Definition: SplatCloud.hh:566
FileBundlePlugin::loadOptionsWidget
QWidget * loadOptionsWidget(QString)
Definition: FileBundle.cc:531
SplatCloud::requestCloudProperty
CloudPropertyT< T > * requestCloudProperty(const PropertyHandleT< T > &_handle)
Request a new property.
Definition: SplatCloudT_impl.hh:232
SplatCloudObject::setName
void setName(QString _name)
Set the name of the Object.
Definition: SplatCloudObject.cc:544
PluginFunctions.hh
ACG::SceneGraph::DrawModes::getDrawMode
const DrawMode & getDrawMode(const std::string &_name)
Get a custom DrawMode.
Definition: DrawModes.cc:807
SplatCloud::colors
Color & colors(int _idx)
Get a reference of the predefined property&#39;s value.
Definition: SplatCloud.hh:633
BaseObject::setFromFileName
void setFromFileName(const QString &_filename)
Definition: BaseObject.cc:716
FileBundlePlugin::saveOptionsWidget
QWidget * saveOptionsWidget(QString)
Definition: FileBundle.cc:522
SplatCloud_Camera
Definition: SplatCloudExtensions.hh:31
SplatCloud::requestPositions
bool requestPositions()
Request the predefined property.
Definition: SplatCloud.hh:561
PluginFunctions::setDrawMode
void setDrawMode(const ACG::SceneGraph::DrawModes::DrawMode &_mode, int _viewer)
Set the draw Mode of a Viewer. .
Definition: PluginFunctions.cc:431
DATA_CAMERA
#define DATA_CAMERA
Definition: Camera.hh:67
LOGERR
Definition: LoggingInterface.hh:96
SplatCloud::positions
Position & positions(int _idx)
Get a reference of the predefined property&#39;s value.
Definition: SplatCloud.hh:631
SplatCloudObject
Definition: SplatCloudObject.hh:76
GlobalOptions.hh
PluginFunctions::getObject
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Definition: PluginFunctions.cc:294
BaseObject::filename
QString filename() const
return the filename of the object
Definition: BaseObject.cc:706
SplatCloud::numSplats
unsigned int numSplats() const
Get the number of splats.
Definition: SplatCloud.hh:179
ACG::SceneGraph::DrawModes::NONE
DrawMode NONE
not a valid draw mode
Definition: DrawModes.cc:71
PluginFunctions::drawMode
ACG::SceneGraph::DrawModes::DrawMode drawMode(int _viewer)
Get the current draw Mode of a Viewer.
Definition: PluginFunctions.cc:450
SplatCloud
Definition: SplatCloud.hh:79
SplatCloud_Projection
Definition: SplatCloudExtensions.hh:14
FileBundlePlugin::name
QString name()
Return a name for the plugin.
Definition: FileBundle.hh:118
ACG::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:288
SplatCloudObject::splatCloud
SplatCloud * splatCloud()
Get SplatCloud.
Definition: SplatCloudObject.hh:162
SplatCloud::clear
void clear()
Remove all properties and reset the number of splats.
Definition: SplatCloud.cc:184
PluginFunctions::splatCloud
SplatCloud * splatCloud(BaseObjectData *_object)
Get a SplatCloud from an object.
Definition: PluginFunctionsSplatCloud.cc:136
ACG::SceneGraph::SplatCloudNode
Definition: SplatCloudNode.hh:89
SplatCloud_CameraManager
Definition: SplatCloudExtensions.hh:83
SplatCloud::requestColors
bool requestColors()
Request the predefined property.
Definition: SplatCloud.hh:562
DataType
Predefined datatypes.
Definition: DataTypes.hh:83
OpenMesh::VectorT
Definition: Vector11T.hh:83
SplatCloud::resizeSplats
void resizeSplats(unsigned int _num)
Resize the data vector of all splat-properties.
Definition: SplatCloud.cc:246
PluginFunctions::splatCloudObject
SplatCloudObject * splatCloudObject(BaseObjectData *_object)
Cast an SplatCloudObject to a SplatCloudObject if possible.
Definition: PluginFunctionsSplatCloud.cc:156
PluginFunctions::splatCloudNode
SplatCloudNode * splatCloudNode(BaseObjectData *_object)
Get a SplatCloudNode from an object.
Definition: PluginFunctionsSplatCloud.cc:116
Camera.hh
ACG::SceneGraph::DrawModes::DrawMode::containsAtomicDrawMode
bool containsAtomicDrawMode(const DrawMode &_atomicDrawMode) const
Check whether an Atomic DrawMode is active in this draw Mode.
Definition: DrawModes.cc:520
SplatCloudObject::splatCloudNode
SplatCloudNode * splatCloudNode()
Get SplatCloud&#39;s scenegraph Node.
Definition: SplatCloudObject.hh:180
SplatCloud::viewlists
Viewlist & viewlists(int _idx)
Get a reference of the predefined property&#39;s value.
Definition: SplatCloud.hh:641
DATA_SPLATCLOUD
#define DATA_SPLATCLOUD
Definition: SplatCloud.hh:59