TextureControl.cc 39 KB
Newer Older
Jan Möbius's avatar
 
Jan Möbius committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//=============================================================================
//
//                               OpenFlipper
//        Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
//                           www.openflipper.org
//
//-----------------------------------------------------------------------------
//
//                                License
//
//  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.
15
//
Jan Möbius's avatar
 
Jan Möbius committed
16
17
18
19
//  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.
20
//
Jan Möbius's avatar
 
Jan Möbius committed
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//  You should have received a copy of the GNU Lesser General Public License
//  along with OpenFlipper.  If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
//
//   $Revision$
//   $Author$
//   $Date$
//
//=============================================================================




35

Jan Möbius's avatar
 
Jan Möbius committed
36
37
38
39
40
#include <QtGui>

#include "TextureControl.hh"

#include <iostream>
41
#include <ACG/GL/GLState.hh>
Jan Möbius's avatar
 
Jan Möbius committed
42
43
44
45

#include "OpenFlipper/BasePlugin/PluginFunctions.hh"
#include "OpenFlipper/common/GlobalOptions.hh"

46
47
48
49
#define TEXTUREDATA "TextureData"



Dirk Wilden's avatar
Dirk Wilden committed
50
51
52
53
54
55
void TextureControlPlugin::slotTextureAdded( QString _textureName , QString _filename , uint _dimension , int _id)
{
  // Get the new object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
    emit log(LOGERR,"Unable to get Object for id " + QString::number(_id) );
56
    return;
Dirk Wilden's avatar
Dirk Wilden committed
57
58
59
60
61
62
63
64
65
  }

  // Get Texture data for this object or create one if it does not exist
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0){
    texData = new TextureData();
    obj->setObjectData(TEXTUREDATA, texData);
  }

66
  if ( texData->textureExists(_textureName) ) {
Dirk Wilden's avatar
Dirk Wilden committed
67
68
69
    emit log(LOGERR,"Trying to add already existing texture " + _textureName + " for object " + QString::number(_id) );
    return;
  }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

  // ================================================================================
  // Get the image file
  // ================================================================================

  QImage textureImage;
  getImage(_filename,textureImage);

  // ================================================================================
  // Add the texture to the texture node and get the corresponding id
  // ================================================================================
  GLuint glName = 0;

  //inform textureNode about the new texture
  if( obj->dataType( DATA_TRIANGLE_MESH ) )
    glName = PluginFunctions::triMeshObject(obj)->textureNode()->add_texture(textureImage);

  if ( obj->dataType( DATA_POLY_MESH ) )
    glName = PluginFunctions::polyMeshObject(obj)->textureNode()->add_texture(textureImage);

  // ================================================================================
  // Store texture information in objects metadata
  // ================================================================================

  if (glName == 0) {
    emit log(LOGERR,"Unable to bind texture!");
    return;
  }

  texData->addTexture(_textureName,_filename,_dimension,glName);
100
  texData->texture(_textureName).disable();
Dirk Wilden's avatar
Dirk Wilden committed
101
102
}

Jan Möbius's avatar
 
Jan Möbius committed
103
104
void TextureControlPlugin::slotTextureAdded( QString _textureName , QString _filename , uint _dimension)
{
105
106
107
  // Add this texture to the list of global textures
  if ( ! globalTextures_.textureExists(_textureName) ) {
    globalTextures_.addTexture(_textureName,_filename,_dimension,0);
108
    globalTextures_.texture(_textureName).disable();
109
110

    QImage textureImage;
111
    getImage(_filename,textureImage);
112
113
    globalTextures_.texture(_textureName).textureImage = textureImage;

114
115
116
117
  } else {
    emit log(LOGERR,"Trying to add already existing global texture " + _textureName );
    return;
  }
118

119
  // Add a new entry to the global Texture menu
Jan Möbius's avatar
 
Jan Möbius committed
120
  QAction* new_texture = new QAction(_textureName, this);
121
  new_texture->setStatusTip(tr("Switch all objects to this Texture ( if available )"));
Jan Möbius's avatar
 
Jan Möbius committed
122
123
124
125
126
  new_texture->setCheckable(true);
  actionGroup_->addAction(new_texture);
  textureMenu_->addAction(new_texture);
  new_texture->setChecked(true);
  textureActions_.push_back(new_texture);
127

128
}
129

130
void TextureControlPlugin::slotMultiTextureAdded( QString _textureGroup , QString _name , QString _filename , int _id , int& _textureId ) {
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
   // Get the new object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
    emit log(LOGERR,"Unable to get Object for id " + QString::number(_id) );
  }

  // Check if we support this kind of data
  if ( !obj->dataType(DATA_TRIANGLE_MESH) && !obj->dataType(DATA_POLY_MESH) ) {
      emit log(LOGERR,"Trying to add textures to object failed because of unsupported object type");
      return;
  }

  // Get Texture data for this object or create one if it does not exist
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0){
    texData = new TextureData();
    obj->setObjectData(TEXTUREDATA, texData);
  }

  if ( !texData->textureExists( _textureGroup ) )
    texData->addMultiTexture( _textureGroup );

  // Add the texture
  slotTextureAdded( _name , _filename , 2 , _id);

  // Get the id of the new texture
  _textureId = -1;
158
  _textureId = texData->texture(_name).id();
159

160
161
162
  //hide the texture (its accessible through the multiTexture)
  texData->texture(_name).hidden( true );

163
164
165
166
167
168
169
170
171
172
173
174
175
  QImage textureImage;
  getImage(_filename,textureImage);
  texData->texture(_name).textureImage = textureImage;

  // Store the new texture in the list of this textureGroup
  if ( _textureId != -1 ) {
    texData->texture(_textureGroup).multiTextureList << _name ;
  } else {
    emit log(LOGERR,"Error when getting internal id of new multitexture!");
  }

}

176
void TextureControlPlugin::getImage( QString _fileName, QImage& _image ) {
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  QString loadFilename;

  if ( _fileName.startsWith("/") )
    loadFilename = _fileName;
  else
    loadFilename = OpenFlipper::Options::textureDirStr() + QDir::separator() + _fileName;

  if ( !_image.load( loadFilename ) ){
        emit log(LOGERR, "Cannot load texture " + _fileName + " at : " + loadFilename);
        _image.load(OpenFlipper::Options::textureDirStr() + QDir::separator() + "unknown.png");
  }

}

void TextureControlPlugin::addedEmptyObject( int _id ) {
  fileOpened(_id);
Jan Möbius's avatar
 
Jan Möbius committed
193
194
}

195
void TextureControlPlugin::fileOpened( int _id ) {
196
  // TODO:: Store original texture coords in a new property!
Jan Möbius's avatar
Jan Möbius committed
197

198
199
200
201
202
203
204
205
206
207
  // Get the new object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
    emit log(LOGERR,"Unable to get Object for id " + QString::number(_id) );
  }

  // Check if we support this kind of data
  if ( !obj->dataType(DATA_TRIANGLE_MESH) && !obj->dataType(DATA_POLY_MESH) ) {
      emit log(LOGERR,"Trying to add textures to object failed because of unsupported object type");
      return;
208
209
  }

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  // Get Texture data for this object or create one if it does not exist
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0){
    texData = new TextureData();
    obj->setObjectData(TEXTUREDATA, texData);
  }

  // Iterate over all available global textures and add them to the object
  for ( uint i = 0 ; i < globalTextures_.textures().size() ; ++i) {

    // ================================================================================
    // Get the image file
    // ================================================================================

    QImage textureImage;
225
    getImage(globalTextures_.textures()[i].filename(),textureImage);
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

    // ================================================================================
    // Add the texture to the texture node and get the corresponding id
    // ================================================================================
    GLuint glName = 0;

    //inform textureNode about the new texture
    if( obj->dataType( DATA_TRIANGLE_MESH ) )
      glName = PluginFunctions::triMeshObject(obj)->textureNode()->add_texture(textureImage);

    if ( obj->dataType( DATA_POLY_MESH ) )
      glName = PluginFunctions::polyMeshObject(obj)->textureNode()->add_texture(textureImage);

    // ================================================================================
    // Store texture information in objects metadata
    // ================================================================================

243
    if (glName != 0) {
244
      texData->addTexture(globalTextures_.textures()[i], glName);
245
      texData->setImage(globalTextures_.textures()[i].name(),textureImage);
246
247
248
249
250
251
    }
    else {
      emit log(LOGERR,"Unable to bind Texture");
      continue;
    }

252
253
254
255
256

    // ================================================================================
    // Update texture mapping in meshNode
    // ================================================================================
    if( obj->dataType( DATA_TRIANGLE_MESH ) ){
257
258
      PluginFunctions::triMeshObject(obj)->meshNode()->set_texture_map( 0 );
      PluginFunctions::triMeshObject(obj)->meshNode()->set_property_map( 0 );
259
260
261
    }

    if ( obj->dataType( DATA_POLY_MESH ) ){
262
263
      PluginFunctions::polyMeshObject(obj)->meshNode()->set_texture_map( 0 );
      PluginFunctions::polyMeshObject(obj)->meshNode()->set_property_map( 0 );
264
265
    }

Jan Möbius's avatar
 
Jan Möbius committed
266
  }
267
268
269
}

void TextureControlPlugin::slotTextureUpdated( QString _textureName , int _identifier ) {
270

271
272
273
274
275
276
  // ================================================================================
  // Get updated object
  // ================================================================================
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _identifier , obj ) ) {
    emit log(LOGERR,"Unable to get Object for id " + QString::number(_identifier) );
Jan Möbius's avatar
 
Jan Möbius committed
277
278
    return;
  }
279

280
281
282
283
284
285
  // ================================================================================
  // Get objects texture data and verify that texture exists
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0){
    std::cerr << "Texture data not found!" << std::endl;
Jan Möbius's avatar
 
Jan Möbius committed
286
    return;
287
  }
Jan Möbius's avatar
 
Jan Möbius committed
288

289
290
291
  // ================================================================================
  // Check if texture exists
  // ================================================================================
292
  if ( ! texData->textureExists(_textureName) ) {
293
    emit log(LOGERR,"Texture " + _textureName + " not found on object " + QString::number(_identifier) );
294
    return;
295
  }
Jan Möbius's avatar
 
Jan Möbius committed
296

297
298
299
  // ================================================================================
  // If texture is not enabled, mark it as dirty and defer update to visualization update
  // ================================================================================
300
  if ( ! texData->texture(_textureName).enabled() ) {
301
302
303
    texData->texture(_textureName).dirty = true;
    return;
  }
Jan Möbius's avatar
 
Jan Möbius committed
304

305
306
307
308
309
310
311
312
313
314
315
  // ================================================================================
  // As the current texture is active, update it
  // ================================================================================
  if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
    TriMesh* mesh = PluginFunctions::triMesh(obj);
    doUpdateTexture(texData->texture(_textureName), *mesh);
    PluginFunctions::triMeshObject(obj)->textureNode()->set_repeat(texData->texture(_textureName).parameters.repeat);
  } else if ( obj->dataType( DATA_POLY_MESH ) ) {
    PolyMesh* mesh = PluginFunctions::polyMesh(obj);
    doUpdateTexture(texData->texture(_textureName), *mesh);
    PluginFunctions::polyMeshObject(obj)->textureNode()->set_repeat(texData->texture(_textureName).parameters.repeat);
316
  }
Jan Möbius's avatar
 
Jan Möbius committed
317

318
319
320
  // ================================================================================
  // Mark texture as not dirty
  // ================================================================================
321
  texData->texture(_textureName).dirty = false;
Jan Möbius's avatar
 
Jan Möbius committed
322

323
324
325
326
  // ================================================================================
  // Enable the right draw mode and update
  // ================================================================================
  switchDrawMode(false);
Jan Möbius's avatar
 
Jan Möbius committed
327
328
329
}

template< typename MeshT >
330
void TextureControlPlugin::doUpdateTexture ( Texture& _texture, MeshT& _mesh )
Jan Möbius's avatar
 
Jan Möbius committed
331
{
332
  if ( _texture.type == HALFEDGEBASED ) {
333
    if (_texture.dimension() == 1) {
Jan Möbius's avatar
 
Jan Möbius committed
334
335

      OpenMesh::HPropHandleT< double > texture;
336
337
	  if ( ! _mesh.get_property_handle(texture, _texture.name().toStdString() ) ) {
        emit log(LOGERR,"Unable to get property " + _texture.name() );
Jan Möbius's avatar
 
Jan Möbius committed
338
339
340
        return;
      }

341
      copyTexture(_texture, _mesh, texture);
Jan Möbius's avatar
 
Jan Möbius committed
342

343
    } else if ( _texture.dimension() == 2 ) {
Jan Möbius's avatar
 
Jan Möbius committed
344
345

      OpenMesh::HPropHandleT< OpenMesh::Vec2d > texture2D;
346
347
	  if ( ! _mesh.get_property_handle( texture2D, _texture.name().toStdString() ) ) {
        emit log(LOGERR,"Unable to get property " + _texture.name() );
Jan Möbius's avatar
 
Jan Möbius committed
348
349
350
        return;
      }

351
      copyTexture( _texture, _mesh, texture2D);
Jan Möbius's avatar
 
Jan Möbius committed
352

353
    } else
354
      emit log(LOGERR, "Unsupported Texture Dimension " + QString::number(_texture.dimension() ) );
355
  } else if ( _texture.type == VERTEXBASED ) {
356
    if ( _texture.dimension() == 1 ) {
Jan Möbius's avatar
 
Jan Möbius committed
357
358

      OpenMesh::VPropHandleT< double > texture;
359
360
	  if ( ! _mesh.get_property_handle(texture,_texture.name().toStdString() ) ) {
        emit log(LOGERR,"Unable to get property " + _texture.name() );
361
        return;
Jan Möbius's avatar
 
Jan Möbius committed
362
363
      }

364
        copyTexture(_texture, _mesh, texture);
Jan Möbius's avatar
 
Jan Möbius committed
365

366
      } else if ( _texture.dimension() == 2 ) {
Jan Möbius's avatar
 
Jan Möbius committed
367
368

        OpenMesh::VPropHandleT< OpenMesh::Vec2d >  texture2D;
369
370
		  if ( ! _mesh.get_property_handle(texture2D,_texture.name().toStdString() ) ) {
          emit log(LOGERR,"Unable to get property " + _texture.name() );
371
          return;
Jan Möbius's avatar
 
Jan Möbius committed
372
373
        }

374
        copyTexture( _texture, _mesh, texture2D);
Jan Möbius's avatar
 
Jan Möbius committed
375
376

      } /*else if ( textures_[_textureid].dimension == 3 ) {
377

Jan Möbius's avatar
 
Jan Möbius committed
378
        OpenMesh::VPropHandleT< OpenMesh::Vec3d >  scalarField3D;
379
380
        if ( ! _mesh.get_property_handle(scalarField3D,_texture.name) ) {
          emit log(LOGERR,"Unable to get property " + _texture.name );
381
          return;
Jan Möbius's avatar
 
Jan Möbius committed
382
        }
383

Jan Möbius's avatar
 
Jan Möbius committed
384
        copyTexture(_textureid, _mesh, scalarField3D);
385

Jan Möbius's avatar
 
Jan Möbius committed
386
      }*/ else
387
        emit log(LOGERR, "Unsupported Texture Dimension " + QString::number(_texture.dimension() ) );
388

Jan Möbius's avatar
 
Jan Möbius committed
389
390
    } else
      emit log(LOGERR, "Unsupported Texture type");
391

Jan Möbius's avatar
 
Jan Möbius committed
392
393
}

394
395
396
397
398
399
400
401
402
403
void TextureControlPlugin::computeValue(Texture& _texture, double _min, double _max, double& _value) {
   const bool clamp         = _texture.parameters.clamp ;
   const bool center        = _texture.parameters.center;
   const double max_val     = _texture.parameters.max_val;
   const bool abs           = _texture.parameters.abs;
   const double clamp_max   = _texture.parameters.clamp_max;
   const double clamp_min   = _texture.parameters.clamp_min;
   const bool scale         = _texture.parameters.scale;
   const double scaleFactor = fabs(_max) + fabs(_min);
   const bool repeat        = _texture.parameters.repeat;
404

Jan Möbius's avatar
 
Jan Möbius committed
405
406
407
   // Use absolute value as requested by plugin
   if ( abs )
      _value = fabs(_value);
408

Jan Möbius's avatar
 
Jan Möbius committed
409
410
411
412
413
414
415
   // Clamp if requested
   if ( clamp ) {
      if ( _value > clamp_max )
         _value = clamp_max;
      if (_value < clamp_min)
         _value = clamp_min;
   }
416

Jan Möbius's avatar
 
Jan Möbius committed
417
418
419
   // if the texture should not be repeated, scale to 0..1
   if ( ! repeat ) {
      if (! center ) {
420
421
422
        if ( scale) {
          _value /= scaleFactor;
          _value -= _min/scaleFactor;
Jan Möbius's avatar
 
Jan Möbius committed
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
        }
      } else {
         // the values above zero are mapped to 0.5..1 the negative ones to 0.5..0
         if (_value > 0.0) {
            _value /= ( _max * 2.0);
            _value += 0.5;
         } else {
            _value /= ( _min * 2.0);
            _value = 0.5 - _value;
         }
      }
   } else {
      _value -= _min;
      _value *= max_val / (_max - _min);
   }
}

void TextureControlPlugin::slotObjectUpdated(int _identifier)
441
{
442
443
444
445
446
  // ================================================================================
  // Get updated object
  // ================================================================================
  if ( _identifier == -1 )
    return;
447

448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _identifier , obj ) ) {
    emit log(LOGERR,"slotObjectUpdated: Unable to get Object for id " + QString::number(_identifier) );
    return;
  }

  // ================================================================================
  // Get objects texture data and verify that texture exists
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0){
    std::cerr << "slotObjectUpdated: Texture data not found!" << std::endl;
    return;
  }

  // ================================================================================
  // Set all textures to dirty
  // ================================================================================
  // TODO : if not in the texture rendering mode, do not emit update
  // Involves adding a interface part to react on draw mode changes
468
  // basic check implemented
469
470
  for ( uint i = 0; i < texData->textures().size(); ++i ) {
    texData->textures()[i].dirty = true;
471
472
473
474
475
476
477

    bool update = false;
    for ( int j = 0 ; j < PluginFunctions::viewers() ; ++j ) {
       update |= ( PluginFunctions::drawMode(j) == ACG::SceneGraph::DrawModes::SOLID_TEXTURED );
       update |= ( PluginFunctions::drawMode(j) == ACG::SceneGraph::DrawModes::SOLID_TEXTURED_SHADED );
    }

478
    if ( update && texData->textures()[i].enabled() )
479
      emit updateTexture( texData->textures()[i].name() , _identifier );
480
  }
481

Jan Möbius's avatar
 
Jan Möbius committed
482
483
484
}

void TextureControlPlugin::slotUpdateAllTextures( ) {
485
486
487
488
489
490
  std::cerr << "slotUpdateAllTextures: not implemented yet ... might be removed" << std::endl;
  // TODO : Check
//    // Force an update of all textures which are available for the updated object
//    for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS) ; o_it != PluginFunctions::objectsEnd(); ++o_it)
//       for ( uint i = 0 ; i < textures_.size() ; ++i )
//          emit updateTexture( textures_[i].name , o_it->id() );
Jan Möbius's avatar
 
Jan Möbius committed
491
492
493
}

void TextureControlPlugin::slotSetTextureMode(QString _textureName ,QString _mode) {
494

495
496
497
498
499
500
501
  // ================================================================================
  // Update texture settings for global textures
  // ================================================================================
  if ( ! globalTextures_.textureExists(_textureName) ) {
    emit log(LOGERR,"Global texture does not exist: " + _textureName);
    return;
  }
502

503
504
505
506
507
508
509
510
511
512
513
514
  // ================================================================================
  // Parse parameters and update them in the texture data
  // ================================================================================
  Texture& texture = globalTextures_.texture(_textureName);

  int i = 0;
  QString nextString = _mode.section(',',i,i);
  while ( nextString != "" ) {
    QString sectionName = nextString.section('=',0,0);
    QString value = nextString.section('=',1,1);

    if ( sectionName == "clamp" ) {
Dirk Wilden's avatar
Dirk Wilden committed
515
      texture.parameters.clamp = StringToBool(value);
516
517
    } else
    if ( sectionName == "clamp_max" ) {
Dirk Wilden's avatar
Dirk Wilden committed
518
      texture.parameters.clamp_max = value.toDouble();
519
520
    } else
    if ( sectionName == "clamp_min" ) {
Dirk Wilden's avatar
Dirk Wilden committed
521
      texture.parameters.clamp_min = value.toDouble();
522
523
    } else
    if ( sectionName == "max_val" ) {
Dirk Wilden's avatar
Dirk Wilden committed
524
      texture.parameters.max_val = value.toDouble();
525
526
    } else
    if ( sectionName == "repeat" ) {
Dirk Wilden's avatar
Dirk Wilden committed
527
      texture.parameters.repeat = StringToBool(value);
528
529
    } else
    if ( sectionName == "center" ) {
Dirk Wilden's avatar
Dirk Wilden committed
530
      texture.parameters.center = StringToBool(value);
531
532
    } else
    if ( sectionName == "scale" ) {
Dirk Wilden's avatar
Dirk Wilden committed
533
      texture.parameters.scale = StringToBool(value);
534
535
536
537
538
539
540
541
542
    } else
    if ( sectionName == "type" ) {
        if (value == "halfedgebased") {
            texture.type = HALFEDGEBASED;
        } else {
            texture.type = VERTEXBASED;
        }
    } else
      emit log(LOGERR,"Unknown texture mode : " + sectionName);
543

544
545
546
    ++i;
    nextString = _mode.section(',',i,i);
  }
547

548
549
550
551
  // ================================================================================
  // Mark updated texture as dirty
  // ================================================================================
  texture.dirty = true;
552

553

Dirk Wilden's avatar
Dirk Wilden committed
554
555
556
557
  // check if the local textures need to be updated
  for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS) ; o_it != PluginFunctions::objectsEnd(); ++o_it){

    TextureData* texData = dynamic_cast< TextureData* > ( o_it->objectData(TEXTUREDATA) );
558

Dirk Wilden's avatar
Dirk Wilden committed
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
    if (texData != 0){

      if ( texData->textureExists(_textureName) ){

        Texture& localTex = texData->texture(_textureName);

        //check if something changed
        bool changed = false;

        if ( _mode.contains("clamp") && (texture.parameters.clamp != localTex.parameters.clamp) ){
          localTex.parameters.clamp = texture.parameters.clamp;
          changed = true;
        }

        if ( _mode.contains("clamp_max") && (texture.parameters.clamp_max != localTex.parameters.clamp_max) ){
          localTex.parameters.clamp_max = texture.parameters.clamp_max;
          changed = true;
        }

        if ( _mode.contains("clamp_min") && (texture.parameters.clamp_min != localTex.parameters.clamp_min) ){
          localTex.parameters.clamp_min = texture.parameters.clamp_min;
          changed = true;
        }

        if ( _mode.contains("max_val") && (texture.parameters.max_val != localTex.parameters.max_val) ){
          localTex.parameters.max_val = texture.parameters.max_val;
          changed = true;
        }

        if ( _mode.contains("repeat") && (texture.parameters.repeat != localTex.parameters.repeat) ){
          localTex.parameters.repeat = texture.parameters.repeat;
          changed = true;
        }

        if ( _mode.contains("center") && (texture.parameters.center != localTex.parameters.center) ){
          localTex.parameters.center = texture.parameters.center;
          changed = true;
        }

        if ( _mode.contains("scale") && (texture.parameters.scale != localTex.parameters.scale) ){
          localTex.parameters.scale = texture.parameters.scale;
          changed = true;
        }

        if ( _mode.contains("type") && (texture.type != localTex.type) ){
          localTex.type = texture.type;
          changed = true;
        }

        //only update if the texture is enabled
        if (changed){
          if ( texData->isEnabled(_textureName) )
            emit updateTexture( _textureName, o_it->id() );
          else
            localTex.dirty = true;
        }
      }
    }
  }
Jan Möbius's avatar
 
Jan Möbius committed
618
619
}

Dirk Wilden's avatar
Dirk Wilden committed
620
621
622
623
624
625
626
bool TextureControlPlugin::StringToBool(QString _value){
  if (_value == "false")
    return false;
  else
    return true;
}

Dirk Wilden's avatar
Dirk Wilden committed
627
void TextureControlPlugin::slotSetTextureMode(QString _textureName, QString _mode, int _id) {
Dirk Wilden's avatar
Dirk Wilden committed
628

Dirk Wilden's avatar
Dirk Wilden committed
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
  // Get the new object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
    emit log(LOGERR,"Unable to get Object for id " + QString::number(_id) );
  }

  // Get Texture data for this object
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );

  if ( texData == 0 || ( !texData->textureExists(_textureName))  ) {
    emit log(LOGERR,"Texture does not exist: " + _textureName + " (object=" + QString::number(_id) + ")");
    return;
  }

  // ================================================================================
  // Parse parameters and update them in the texture data
  // ================================================================================
  Texture& texture = texData->texture(_textureName);

Dirk Wilden's avatar
Dirk Wilden committed
648
649
  bool changed = false;

Dirk Wilden's avatar
Dirk Wilden committed
650
651
652
653
654
655
656
  int i = 0;
  QString nextString = _mode.section(',',i,i);
  while ( nextString != "" ) {
    QString sectionName = nextString.section('=',0,0);
    QString value = nextString.section('=',1,1);

    if ( sectionName == "clamp" ) {
Dirk Wilden's avatar
Dirk Wilden committed
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
      if ( StringToBool(value) != texture.parameters.clamp ) {
        texture.parameters.clamp = StringToBool(value);
        changed = true;
      }
    } else if ( sectionName == "clamp_max" ) {
      if (value.toDouble() != texture.parameters.clamp_max){
        texture.parameters.clamp_max = value.toDouble();
        changed = true;
      }
    } else if ( sectionName == "clamp_min" ) {
      if (value.toDouble() != texture.parameters.clamp_min){
        texture.parameters.clamp_min = value.toDouble();
        changed = true;
      }
    } else if ( sectionName == "max_val" ) {
      if (value.toDouble() != texture.parameters.max_val){
        texture.parameters.max_val = value.toDouble();
        changed = true;
      }
    } else if ( sectionName == "repeat" ) {
      if ( StringToBool(value) != texture.parameters.repeat ) {
        texture.parameters.repeat = StringToBool(value);
        changed = true;
      }
    } else if ( sectionName == "center" ) {
      if ( StringToBool(value) != texture.parameters.center ) {
        texture.parameters.center = StringToBool(value);
        changed = true;
      }
    } else if ( sectionName == "scale" ) {
      if ( StringToBool(value) != texture.parameters.scale ) {
        texture.parameters.scale = StringToBool(value);
        changed = true;
      }
    } else if ( sectionName == "type" ) {
Dirk Wilden's avatar
Dirk Wilden committed
692
        if (value == "halfedgebased") {
Dirk Wilden's avatar
Dirk Wilden committed
693
694
          texture.type = HALFEDGEBASED;
          changed = true;
Dirk Wilden's avatar
Dirk Wilden committed
695
        } else {
Dirk Wilden's avatar
Dirk Wilden committed
696
697
          texture.type = VERTEXBASED;
          changed = true;
Dirk Wilden's avatar
Dirk Wilden committed
698
699
700
701
702
703
704
705
        }
    } else
      emit log(LOGERR,"Unknown texture mode : " + sectionName);

    ++i;
    nextString = _mode.section(',',i,i);
  }

Dirk Wilden's avatar
Dirk Wilden committed
706
707
708
709
710
711
712
  //only update if the texture is enabled
  if (changed){
    if ( texData->isEnabled(_textureName) )
      emit updateTexture( _textureName, _id );
    else
      texture.dirty = true;
  }
Dirk Wilden's avatar
Dirk Wilden committed
713
714
}

Jan Möbius's avatar
 
Jan Möbius committed
715
void TextureControlPlugin::pluginsInitialized() {
716
717
718
  // ================================================================================
  // Create global texture menu
  // ================================================================================
Jan Möbius's avatar
 
Jan Möbius committed
719
  textureMenu_ = new QMenu(tr("&Texture Control"));
720
  textureMenu_->setTearOffEnabled(true);
Jan Möbius's avatar
   
Jan Möbius committed
721
  emit addMenubarAction(textureMenu_->menuAction(), VIEWMENU );
722

723
724
725
726
  // ================================================================================
  // Create Settings dialog
  // ================================================================================
  // TODO : Settings dialog updates required to change global/local textures,...
Jan Möbius's avatar
 
Jan Möbius committed
727
  settingsDialog_ = new texturePropertiesWidget(0);
728
729
  connect( settingsDialog_, SIGNAL( applyProperties(TextureData*,QString,int) ),
           this,              SLOT( applyDialogSettings(TextureData*,QString,int) ));
730

731
732
733
  // ================================================================================
  // Create action group and menu for global textures
  // ================================================================================
Jan Möbius's avatar
 
Jan Möbius committed
734
735
736
737
  actionGroup_ = new QActionGroup( 0 );
  actionGroup_->setExclusive( true );
  connect( actionGroup_, SIGNAL( triggered( QAction * ) ),
          this, SLOT( slotTextureMenu( QAction * ) ) );
738

Jan Möbius's avatar
 
Jan Möbius committed
739
740
741
742
  QAction* AC_Texture_Settings = new QAction(tr("&Texture Settings"), this);
  AC_Texture_Settings->setStatusTip(tr("Set the texture visualization properties"));
  connect(AC_Texture_Settings, SIGNAL(triggered()), this, SLOT(slotSetTextureProperties()));
  textureMenu_->addAction(AC_Texture_Settings);
743

Jan Möbius's avatar
 
Jan Möbius committed
744
745
  textureMenu_->addSeparator();
  textureMenu_->addActions(actionGroup_->actions());
746
747
748
749
750
751
752
753
754

  // ================================================================================
  // Create basic per object context menu
  // ================================================================================
  contextMenu_ = new QMenu(0);
  contextMenu_->setTitle("Textures");
  emit addContextMenuItem(contextMenu_->menuAction() ,DATA_TRIANGLE_MESH , CONTEXTOBJECTMENU );
  emit addContextMenuItem(contextMenu_->menuAction() ,DATA_POLY_MESH     , CONTEXTOBJECTMENU );

Jan Möbius's avatar
 
Jan Möbius committed
755
}
756

Jan Möbius's avatar
Jan Möbius committed
757
void TextureControlPlugin::slotSetTextureProperties() {
758

759
  settingsDialog_->show( &globalTextures_, -1);
Jan Möbius's avatar
 
Jan Möbius committed
760
}
761

762
void TextureControlPlugin::applyDialogSettings(TextureData* _texData, QString _textureName, int _id) {
763

764
765
766
767
768
769
770
  if (_id != -1){
    //local texture
    if ( _texData->isEnabled(_textureName) ){
      slotTextureUpdated( _textureName  , _id );
      emit updateView();
    }else
      _texData->texture( _textureName ).dirty = true;
771

772
773
774
775
776
777
778
779
780
781
782
  } else {
    // global texture

    _texData->texture( _textureName ).dirty = true;

    Texture& globalTexture = _texData->texture(_textureName);

    // check if the local textures need to be updated
    for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS) ; o_it != PluginFunctions::objectsEnd(); ++o_it){

      TextureData* texData = dynamic_cast< TextureData* > ( o_it->objectData(TEXTUREDATA) );
Jan Möbius's avatar
 
Jan Möbius committed
783

784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
      if ( texData != 0 && texData->textureExists(_textureName) ){

        //overwrite local parameters
        Texture& localTexture = texData->texture(_textureName);

        bool changed = false;

        if (localTexture.parameters.clamp != globalTexture.parameters.clamp){
          localTexture.parameters.clamp = globalTexture.parameters.clamp;
          changed = true;
        }
        if (localTexture.parameters.clamp_max != globalTexture.parameters.clamp_max){
          localTexture.parameters.clamp_max = globalTexture.parameters.clamp_max;
          changed = true;
        }
        if (localTexture.parameters.clamp_min != globalTexture.parameters.clamp_min){
          localTexture.parameters.clamp_min = globalTexture.parameters.clamp_min;
          changed = true;
        }
        if (localTexture.parameters.max_val != globalTexture.parameters.max_val){
          localTexture.parameters.max_val = globalTexture.parameters.max_val;
          changed = true;
        }
        if (localTexture.parameters.repeat != globalTexture.parameters.repeat){
          localTexture.parameters.repeat = globalTexture.parameters.repeat;
          changed = true;
        }
        if (localTexture.parameters.center != globalTexture.parameters.center){
          localTexture.parameters.center = globalTexture.parameters.center;
          changed = true;
        }
        if (localTexture.parameters.scale != globalTexture.parameters.scale){
          localTexture.parameters.scale = globalTexture.parameters.scale;
          changed = true;
        }

        // update if something has changed
        if ( changed ){
          if ( texData->isEnabled(_textureName) )
            slotTextureUpdated( _textureName  , o_it->id() );
          else
            texData->texture( _textureName ).dirty = true;
        }
      }
    }
  }
}
831

Jan Möbius's avatar
 
Jan Möbius committed
832
void TextureControlPlugin::slotTextureMenu(QAction* _action) {
833
834
  // call existing function to switch the texture
  slotSwitchTexture( _action->text() );
Jan Möbius's avatar
 
Jan Möbius committed
835
836
}

Dirk Wilden's avatar
Dirk Wilden committed
837
void TextureControlPlugin::doSwitchTexture( QString _textureName , int _id ) {
838

Dirk Wilden's avatar
Dirk Wilden committed
839
840
841
842
843
  // Get the new object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
    emit log(LOGERR,"Unable to get Object for id " + QString::number(_id) );
  }
844

Dirk Wilden's avatar
Dirk Wilden committed
845
846
847
848
849
850
851
852
  // ================================================================================
  // Get Texture data for current object
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0) {
    std::cerr << "Object has no texture data" << std::endl;
    return;
  }
853

Dirk Wilden's avatar
Dirk Wilden committed
854
  // ================================================================================
855
  // Check for requested Texture
Dirk Wilden's avatar
Dirk Wilden committed
856
  // ================================================================================
857
858
  if ( !texData->textureExists(_textureName) ) {
    emit log(LOGERR, "Texture not available! " + _textureName );
Dirk Wilden's avatar
Dirk Wilden committed
859
860
    return;
  }
861

862
863
864
865
866
867
868
869
870
871
872
873
874
875
  // ================================================================================
  // Enable the given texture exclusively or use multitexture setting
  // ================================================================================
  bool multiTextureMode = ( texData->texture(_textureName).type == MULTITEXTURE );
  if ( !multiTextureMode ) {
    if ( ! texData->enableTexture( _textureName , true ) ) {
      emit log(LOGERR, "Failed to enabled Texture " + _textureName );
      return;
    }
  } else {
    // get the list of textures for this mode
    QStringList textureList = texData->texture(_textureName).multiTextureList;

    for ( uint i = 0 ; i < texData->textures().size() ; ++i ) {
876
877
      if ( textureList.contains( texData->textures()[i].name() ) )
        texData->enableTexture( texData->textures()[i].name() , false );
878
       else
879
        texData->disableTexture( texData->textures()[i].name() );
880
881
882
883
884
885

    }

    std::cerr << "Trying to enable multitexture" << std::endl;
  }

Dirk Wilden's avatar
Dirk Wilden committed
886
887
888
889
  // ================================================================================
  // If texture is flagged dirty, update it ( this jumps to texture updated
  // which will update the visualization )
  // ================================================================================
890
  if ( !multiTextureMode && texData->texture( _textureName).dirty ) {
Dirk Wilden's avatar
Dirk Wilden committed
891
    // TODO: maybe introduce lock to prevent extra redraws if updating all objects
892
    emit updateTexture( texData->texture( _textureName ).name() , obj->id() );
Dirk Wilden's avatar
Dirk Wilden committed
893
894
    return;
  }
895

Dirk Wilden's avatar
Dirk Wilden committed
896
897
898
899
  // ================================================================================
  // Update texture map from meshNode and activate it
  // ================================================================================
  if( obj->dataType( DATA_TRIANGLE_MESH ) ){
900
901
    if (!multiTextureMode) {
      doUpdateTexture(texData->texture(_textureName), *PluginFunctions::triMeshObject(obj)->mesh());
902
      PluginFunctions::triMeshObject(obj)->textureNode()->activateTexture( texData->texture( _textureName ).glName() );
903
904
905
906
907
908
909
      PluginFunctions::triMeshObject(obj)->meshNode()->set_texture_map( 0 );
      PluginFunctions::triMeshObject(obj)->meshNode()->set_property_map( 0 );
    } else {
      PluginFunctions::triMeshObject(obj)->meshNode()->set_texture_map( texData->textureMap() );
      PluginFunctions::triMeshObject(obj)->meshNode()->set_property_map( 0 );
    }

Dirk Wilden's avatar
Dirk Wilden committed
910
  }
911

Dirk Wilden's avatar
Dirk Wilden committed
912
  if ( obj->dataType( DATA_POLY_MESH ) ){
913
914
    if (!multiTextureMode) {
      doUpdateTexture(texData->texture(_textureName), *PluginFunctions::polyMeshObject(obj)->mesh());
915
      PluginFunctions::polyMeshObject(obj)->textureNode()->activateTexture( texData->texture( _textureName ).glName() );
916
917
918
919
920
921
      PluginFunctions::polyMeshObject(obj)->meshNode()->set_texture_map( 0 );
      PluginFunctions::polyMeshObject(obj)->meshNode()->set_property_map( 0 );
    } else {
      PluginFunctions::polyMeshObject(obj)->meshNode()->set_texture_map( texData->textureMap() );
      PluginFunctions::polyMeshObject(obj)->meshNode()->set_property_map( 0 );
    }
Dirk Wilden's avatar
Dirk Wilden committed
922
923
924
925
926
  }

  // ================================================================================
  // Switch to a texture drawMode
  // ================================================================================
927
928
929
930
931
932
  switchDrawMode(multiTextureMode);

}

void TextureControlPlugin::switchDrawMode( bool _multiTexture ) {

Dirk Wilden's avatar
Dirk Wilden committed
933
934
  bool textureMode = false;
  for ( int j = 0 ; j < PluginFunctions::viewers() ; ++j ) {
935
936
937
938
939
940
941
      if ( _multiTexture ) {
        textureMode |= ( PluginFunctions::drawMode(j) == ACG::SceneGraph::DrawModes::SOLID_2DTEXTURED_FACE );
        textureMode |= ( PluginFunctions::drawMode(j) == ACG::SceneGraph::DrawModes::SOLID_2DTEXTURED_FACE_SHADED );
      } else {
        textureMode |= ( PluginFunctions::drawMode(j) == ACG::SceneGraph::DrawModes::SOLID_TEXTURED );
        textureMode |= ( PluginFunctions::drawMode(j) == ACG::SceneGraph::DrawModes::SOLID_TEXTURED_SHADED );
      }
Jan Möbius's avatar
 
Jan Möbius committed
942
  }
943

944
945
946
947
948
949
  if ( !textureMode ) {
    if ( _multiTexture )
      PluginFunctions::setDrawMode( ACG::SceneGraph::DrawModes::SOLID_2DTEXTURED_FACE_SHADED );
    else
      PluginFunctions::setDrawMode( ACG::SceneGraph::DrawModes::SOLID_TEXTURED_SHADED );
  }
Dirk Wilden's avatar
Dirk Wilden committed
950
951

  emit updateView();
952
}
Dirk Wilden's avatar
Dirk Wilden committed
953

954
void TextureControlPlugin::slotSwitchTexture( QString _textureName , int _id ) {
Dirk Wilden's avatar
Dirk Wilden committed
955

956
  doSwitchTexture(_textureName, _id);
Dirk Wilden's avatar
Dirk Wilden committed
957
958
959
960
961
962
963
964
965
966
}

void TextureControlPlugin::slotSwitchTexture( QString _textureName ) {

  for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS) ;
                                        o_it != PluginFunctions::objectsEnd();
                                        ++o_it)

    doSwitchTexture(_textureName, o_it->id() );

Jan Möbius's avatar
 
Jan Möbius committed
967
968
969
}


970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
void TextureControlPlugin::slotUpdateContextMenu( int _objectId ) {

  std::cerr << "TextureControlPlugin::slotUpdateContextMenu " << _objectId << std::endl;

  // ================================================================================
  // Get picking object object
  // ================================================================================
  if ( _objectId == -1 )
    return;

  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _objectId , obj ) ) {
    emit log(LOGERR,"slotUpdateContextMenu: Unable to get Object for id " + QString::number(_objectId) );
    return;
  }

  // ================================================================================
  // Get objects texture data and verify that texture exists
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0){
    std::cerr << "TextureControlPlugin::slotUpdateContextMenu: Texture data not found!" << std::endl;
    return;
  }

  // ================================================================================
  // Prepare Texture menu
  // ================================================================================
  contextMenu_->clear();
  QActionGroup* actionGroup = new QActionGroup(0);
  actionGroup->setExclusive( true );
For faster browsing, not all history is shown. View entire blame