Developer Documentation
TextureControl.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 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 #include "TextureControl.hh"
52 
53 #include "ImageStorage.hh"
54 
55 #if QT_VERSION >= 0x050000
56 #else
57 #include <QtGui>
58 #endif
59 
60 #ifdef ENABLE_OPENVOLUMEMESH_SUPPORT
61 #endif
62 
63 #define TEXTUREDATA "TextureData"
64 
65 
66 
68 settingsDialog_(0),
69 textureMenu_(0),
70 actionGroup_(0),
71 contextMenu_(0)
72 {
73 
74 }
75 
76 void TextureControlPlugin::slotTextureAdded( QString _textureName , QString _filename , uint _dimension , int _id)
77 {
78  // Get the new object
79  BaseObjectData* obj;
80  if (! PluginFunctions::getObject( _id , obj ) ) {
81  emit log(LOGERR,"slotTextureAdded: Unable to get Object for id " + QString::number(_id) );
82  return;
83  }
84 
85  // Get Texture data for this object or create one if it does not exist
86  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
87  if (texData == 0){
88  texData = new TextureData();
89  obj->setObjectData(TEXTUREDATA, texData);
90  }
91 
92  if ( texData->textureExists(_textureName) ) {
93  emit log(LOGERR,"slotTextureAdded: Trying to add already existing texture " + _textureName + " for object " + QString::number(_id) );
94  return;
95  }
96 
97  // ================================================================================
98  // Get the image file
99  // ================================================================================
100 
101  // Add Image to the image store and set the index in the texture description
102  int newId = imageStore().addImageFile(_filename);
103 
104  if ( newId == -1 ) {
105  emit log(LOGERR,imageStore().error());
106  return;
107  }
108 
109  // ================================================================================
110  // Add the texture to the texture node and get the corresponding id
111  // ================================================================================
112  GLuint glName = 0;
113 
114  //inform textureNode about the new texture
115  if( obj->dataType( DATA_TRIANGLE_MESH ) )
116  glName = PluginFunctions::triMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newId,0));
117 
118  if ( obj->dataType( DATA_POLY_MESH ) )
119  glName = PluginFunctions::polyMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newId,0));
120 
121 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
122  if ( obj->dataType( DATA_HEXAHEDRAL_MESH ) )
123  glName = PluginFunctions::hexahedralMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newId,0));
124 #endif
125 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
126  if ( obj->dataType( DATA_POLYHEDRAL_MESH ) )
127  glName = PluginFunctions::polyhedralMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newId,0));
128 #endif
129 
130 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
131  if (obj->dataType(DATA_BSPLINE_SURFACE))
132  glName = PluginFunctions::bsplineSurfaceObject(obj)->textureNode()->add_texture(imageStore().getImage(newId, 0));
133 #endif
134 
135  // ================================================================================
136  // Store texture information in objects metadata
137  // ================================================================================
138 
139  if (glName == 0) {
140  emit log(LOGERR,"slotTextureAdded: Unable to bind texture!");
141  return;
142  }
143 
144  texData->addTexture(_textureName,_filename,_dimension,glName);
145 
146  // Remember id in texture descriptor
147  texData->setImage(_textureName,newId);
148 
149  texData->texture(_textureName).disable();
150 }
151 
152 void TextureControlPlugin::slotTextureAdded( QString _textureName , QString _filename , uint _dimension)
153 {
154  // Add this texture to the list of global textures
155  if ( ! globalTextures_.textureExists(_textureName) ) {
156  globalTextures_.addTexture(_textureName,_filename,_dimension,0);
157  globalTextures_.texture(_textureName).disable();
158 
159  int newImageId = imageStore().addImageFile(_filename);
160 
161  if ( newImageId == -1 ) {
162  emit log(LOGERR,imageStore().error());
163  return;
164  }
165 
166  globalTextures_.texture(_textureName).textureImageId(newImageId);
167 
168  } else {
169  emit log(LOGERR,"slotTextureAdded: Trying to add already existing global texture " + _textureName );
170  return;
171  }
172 
173  // Add a new entry to the global Texture menu
174  QAction* new_texture = new QAction(_textureName, this);
175  new_texture->setStatusTip(tr("slotTextureAdded: Switch all objects to this Texture ( if available )"));
176  new_texture->setCheckable(true);
177  actionGroup_->addAction(new_texture);
178  textureMenu_->addAction(new_texture);
179  new_texture->setChecked(true);
180  textureActions_.push_back(new_texture);
181 
182 }
183 
184 void TextureControlPlugin::slotMultiTextureAdded( QString _textureGroup , QString _name , QString _filename , int _id , int& _textureId ) {
185  // Get the new object
186  BaseObjectData* obj;
187  if (! PluginFunctions::getObject( _id , obj ) ) {
188  emit log(LOGERR,"slotMultiTextureAdded: Unable to get Object for id " + QString::number(_id) );
189  }
190 
191  // Check if we support this kind of data
192  if ( !obj->dataType(DATA_TRIANGLE_MESH) && !obj->dataType(DATA_POLY_MESH) ) {
193  emit log(LOGERR,"slotMultiTextureAdded: Trying to add textures to object failed because of unsupported object type");
194  return;
195  }
196 
197  // Get Texture data for this object or create one if it does not exist
198  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
199  if (texData == 0){
200  texData = new TextureData();
201  obj->setObjectData(TEXTUREDATA, texData);
202  }
203 
204  if ( !texData->textureExists( _textureGroup ) )
205  texData->addMultiTexture( _textureGroup );
206 
207  // Add the texture
208  slotTextureAdded( _name , _filename , 2 , _id);
209 
210  // Get the id of the new texture
211  _textureId = texData->texture(_name).id();
212 
213  //hide the texture (its accessible through the multiTexture)
214  texData->texture(_name).hidden( true );
215 
216  // Add to image store
217  int newImageId = imageStore().addImageFile(_filename);
218 
219  if ( newImageId == -1 ) {
220  emit log(LOGERR,imageStore().error());
221  return;
222  }
223 
224  // Add to texture description
225  texData->texture(_name).textureImageId(newImageId);
226 
227  // Store the new texture in the list of this textureGroup
228  if ( _textureId != -1 ) {
229  texData->texture(_textureGroup).multiTextureList << _name ;
230  } else {
231  emit log(LOGERR,"slotMultiTextureAdded: Error when getting internal id of new multitexture!");
232  }
233 
234 }
235 
236 void TextureControlPlugin::addedEmptyObject( int _id ) {
237 
238  // Get the new object
239  BaseObjectData* obj;
240  if (! PluginFunctions::getObject( _id , obj ) ) {
241 // emit log(LOGERR,"addedEmptyObject: Unable to get Object for id " + QString::number(_id) );
242  return;
243  }
244 
245  // Check if we support this kind of data
246  if ( !obj->dataType(DATA_TRIANGLE_MESH) && !obj->dataType(DATA_POLY_MESH)
247 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
249 #endif
250 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
252 #endif
253 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
255 #endif
256  )
257  {
258  return;
259  }
260 
261  // Get Texture data for this object or create one if it does not exist
262  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
263  if (texData == 0){
264  texData = new TextureData();
265  obj->setObjectData(TEXTUREDATA, texData);
266  }
267 
268  // Iterate over all available global textures and add them to the object
269  for ( uint i = 0 ; i < globalTextures_.textures().size() ; ++i) {
270 
271  // Add to image store
272  int newImageId = imageStore().addImageFile(globalTextures_.textures()[i].filename());
273 
274  if ( newImageId == -1 ) {
275  emit log(LOGERR,imageStore().error());
276  continue;
277  }
278 
279  // ================================================================================
280  // Add the texture to the texture node and get the corresponding id
281  // ================================================================================
282  GLuint glName = 0;
283 
284  //inform textureNode about the new texture
285  if( obj->dataType( DATA_TRIANGLE_MESH ) )
286  glName = PluginFunctions::triMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newImageId,0));
287 
288  if ( obj->dataType( DATA_POLY_MESH ) )
289  glName = PluginFunctions::polyMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newImageId,0));
290 
291 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
292  if( obj->dataType( DATA_HEXAHEDRAL_MESH ) )
293  glName = PluginFunctions::hexahedralMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newImageId,0));
294 #endif
295 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
296  if ( obj->dataType( DATA_POLYHEDRAL_MESH ) )
297  glName = PluginFunctions::polyhedralMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newImageId,0));
298 #endif
299 
300 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
301  if (obj->dataType(DATA_BSPLINE_SURFACE))
302  glName = PluginFunctions::bsplineSurfaceObject(obj)->textureNode()->add_texture(imageStore().getImage(newImageId, 0));
303 #endif
304 
305  // ================================================================================
306  // Store texture information in objects metadata
307  // ================================================================================
308  if (glName != 0) {
309  texData->addTexture(globalTextures_.textures()[i], glName);
310 
311  // Add to texture description
312  texData->setImage(globalTextures_.textures()[i].name(),newImageId);
313  }
314  else {
315  imageStore().removeImage(newImageId);
316  emit log(LOGERR,"addedEmptyObject: Unable to bind Texture");
317  continue;
318  }
319 
320 
321  // ================================================================================
322  // Update texture mapping in meshNode
323  // ================================================================================
324  if( obj->dataType( DATA_TRIANGLE_MESH ) ){
326  }
327 
328  if ( obj->dataType( DATA_POLY_MESH ) ){
330  }
331 
332  }
333 }
334 
335 template< typename MeshT >
336 void TextureControlPlugin::handleFileOpenTextures( MeshT*& _mesh , int _objectId ) {
337 
338  // Get the new object
339  BaseObjectData* obj;
340  if (! PluginFunctions::getObject( _objectId , obj ) ) {
341  return;
342  }
343 
344  if ( _mesh->has_vertex_texcoords2D() ){
345  slotTextureAdded("Original Per Vertex Texture Coords","unknown.png",2,_objectId);
346  slotSetTextureMode("Original Per Vertex Texture Coords","type=vertexbased",_objectId);
347  }
348 
349  if ( _mesh->has_halfedge_texcoords2D() ){
350  slotTextureAdded("Original Per Face Texture Coords","unknown.png",2,_objectId);
351  slotSetTextureMode("Original Per Face Texture Coords","type=halfedgebased",_objectId);
352  }
353 
354 }
355 
356 #ifdef ENABLE_OPENVOLUMEMESH_SUPPORT
357 template< typename VolumeMeshObjectT >
358 void TextureControlPlugin::handleFileOpenTexturesOVM( VolumeMeshObjectT* _obj, int _objectId ) {
359 
360  if ( _obj->texcoords().vertex_texcoords_available() ){
361  slotTextureAdded("Original Per Vertex Texture Coords","unknown.png",2,_objectId);
362  slotSetTextureMode("Original Per Vertex Texture Coords","type=vertexbased",_objectId);
363  }
364 
365 }
366 #endif
367 
368 void TextureControlPlugin::fileOpened( int _id ) {
369  // TODO:: Store original texture coords in a new property!
370 
371  // Get the new object
372  BaseObjectData* obj;
373  if (! PluginFunctions::getObject( _id , obj ) ) {
374  emit log(LOGERR,"fileOpened: Unable to get Object for id " + QString::number(_id) );
375  return;
376  }
377 
378  // Check if we support this kind of data
379  if ( !obj->dataType(DATA_TRIANGLE_MESH) && !obj->dataType(DATA_POLY_MESH)
380 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
382 #endif
383 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
385 #endif
386  )
387  {
388  return;
389  }
390 
391  // Get Texture data for this object or create one if it does not exist
392  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
393  if (texData == 0){
394  emit log(LOGERR,tr("fileOpened: Unable to get texture object data for id %1.").arg(_id) );
395  return;
396  }
397 
398  // Check if the file contains a texture map, store original textures and handle them before adding global textures
399  if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
400  TriMesh* mesh = PluginFunctions::triMesh(obj);
401  if ( mesh )
402  handleFileOpenTextures(mesh,_id);
403  } else if ( obj->dataType( DATA_POLY_MESH ) ) {
404  PolyMesh* mesh = PluginFunctions::polyMesh(obj);
405  if ( mesh )
406  handleFileOpenTextures(mesh,_id);
407  }
408 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
409  else if ( obj->dataType( DATA_HEXAHEDRAL_MESH ) ) {
411  handleFileOpenTexturesOVM(ovm_obj, _id);
412  }
413 #endif
414 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
415  else if ( obj->dataType( DATA_POLYHEDRAL_MESH ) ) {
417  handleFileOpenTexturesOVM(ovm_obj, _id);
418  }
419 #endif
420 
421 }
422 
423 void TextureControlPlugin::slotTextureChangeImage( QString _textureName , QImage& _image , int _id ) {
424 
425  // ================================================================================
426  // Get the new object
427  // ================================================================================
428  BaseObjectData* obj;
429  if (! PluginFunctions::getObject( _id , obj ) ) {
430  emit log(LOGERR,"slotTextureChangeImage: Unable to get Object for id " + QString::number(_id) );
431  }
432 
433  // ================================================================================
434  // Get Texture data for this object
435  // ================================================================================
436  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
437 
438  if ( texData == 0 || ( !texData->textureExists(_textureName)) ) {
439  emit log(LOGERR,"slotTextureChangeImage: Texture does not exist: " + _textureName + " (objectid=" + QString::number(_id) + ")");
440  return;
441  }
442 
443  // ================================================================================
444  // Update the image
445  // ================================================================================
446  Texture& texture = texData->texture(_textureName);
447 
448  // Add to image store
449  int newImageId = imageStore().addImage(_image);
450 
451  // Add to texture description
452  texture.textureImageId(newImageId);
453 
454  // ================================================================================
455  // Flag dirty or update
456  // ================================================================================
457 
458  if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
459  PluginFunctions::triMeshObject(obj)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
460  } else if ( obj->dataType( DATA_POLY_MESH ) ) {
461  PluginFunctions::triMeshObject(obj)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
462  }
463 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
464  else if ( obj->dataType( DATA_HEXAHEDRAL_MESH ) ) {
465  PluginFunctions::hexahedralMeshObject(obj)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
466  }
467 #endif
468 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
469  else if ( obj->dataType( DATA_POLYHEDRAL_MESH ) ) {
470  PluginFunctions::polyhedralMeshObject(obj)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
471  }
472 #endif
473 
474 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
475  else if (obj->dataType(DATA_BSPLINE_SURFACE)) {
476  PluginFunctions::bsplineSurfaceObject(obj)->textureNode()->set_texture(_image, texData->texture(_textureName).glName());
477  }
478 #endif
479 
480  emit updateView();
481 
482 }
483 
484 void TextureControlPlugin::slotTextureChangeImage( QString _textureName , QImage& _image ) {
485 
486  // ================================================================================
487  // Update texture Image for global textures
488  // ================================================================================
489  if ( ! globalTextures_.textureExists(_textureName) ) {
490  emit log(LOGERR,"slotTextureChangeImage: Global texture does not exist: " + _textureName);
491  return;
492  }
493 
494  // ================================================================================
495  // Update the image in the global texture
496  // ================================================================================
497  Texture& texture = globalTextures_.texture(_textureName);
498 
499  // Add to image store
500  int newImageId = imageStore().addImage(_image);
501 
502  // Add to texture description
503  texture.textureImageId(newImageId);
504 
505  // ================================================================================
506  // check if the local textures need to be updated
507  // ================================================================================
509 
510  TextureData* texData = dynamic_cast< TextureData* > ( o_it->objectData(TEXTUREDATA) );
511  if (texData != 0)
512  if ( texData->textureExists(_textureName) ){
513  Texture& localTex = texData->texture(_textureName);
514  localTex.textureImageId(newImageId);
515 
516  if( o_it->dataType( DATA_TRIANGLE_MESH ) ) {
517  PluginFunctions::triMeshObject(o_it)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
518  } else if ( o_it->dataType( DATA_POLY_MESH ) ) {
519  PluginFunctions::triMeshObject(o_it)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
520  }
521 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
522  else if ( o_it->dataType( DATA_HEXAHEDRAL_MESH ) ) {
523  PluginFunctions::hexahedralMeshObject(o_it)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
524  }
525 #endif
526 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
527  else if ( o_it->dataType( DATA_POLYHEDRAL_MESH ) ) {
528  PluginFunctions::polyhedralMeshObject(o_it)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
529  }
530 #endif
531 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
532  else if (o_it->dataType(DATA_BSPLINE_SURFACE)) {
533  PluginFunctions::bsplineSurfaceObject(o_it)->textureNode()->set_texture(_image, texData->texture(_textureName).glName());
534  }
535 #endif
536  }
537  }
538 
539  emit updateView();
540 
541 }
542 
543 void TextureControlPlugin::slotTextureGetImage( QString _textureName, QImage& _image, int _id ){
544 
545  // Get the object
546  BaseObjectData* obj;
547  if (! PluginFunctions::getObject( _id , obj ) ) {
548  emit log(LOGERR,"slotTextureGetImage: Unable to get Object for id " + QString::number(_id) );
549  }
550 
551  // ================================================================================
552  // Get Texture data for current object
553  // ================================================================================
554  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
555  if (texData == 0) {
556  emit log(LOGERR, tr("slotTextureGetImage: Object has no texture data! Object: %1").arg(_id) );
557  return;
558  }
559 
560  // ================================================================================
561  // Check for requested Texture
562  // ================================================================================
563  if ( !texData->textureExists(_textureName) ) {
564  emit log(LOGERR, "slotTextureGetImage: Texture not available! " + _textureName );
565  return;
566  }
567 
568  if ( texData->texture(_textureName).type() == MULTITEXTURE )
569  _image = QImage();
570  else
571  _image = imageStore().getImage(texData->texture(_textureName).textureImageId(),0 );
572 }
573 
574 
575 void TextureControlPlugin::slotTextureGetImage( QString _textureName, QImage& _image ){
576 
577  if ( ! globalTextures_.textureExists(_textureName) ) {
578  emit log(LOGERR,"slotTextureGetImage: Global texture does not exist: " + _textureName);
579  return;
580  }
581 
582  if ( globalTextures_.texture(_textureName).type() == MULTITEXTURE )
583  _image = QImage();
584  else
585  _image = imageStore().getImage(globalTextures_.texture(_textureName).textureImageId(),0);
586 }
587 
588 void TextureControlPlugin::slotTextureIndex( QString _textureName, int _id, int& _index){
589 
590  // Get the object
591  BaseObjectData* obj;
592  if (! PluginFunctions::getObject( _id , obj ) ) {
593  emit log(LOGERR,"slotTextureIndex: Unable to get Object for id " + QString::number(_id) );
594  }
595 
596  // ================================================================================
597  // Get Texture data for current object
598  // ================================================================================
599  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
600  if (texData == 0) {
601  emit log(LOGERR, tr("slotTextureIndex: Object has no texture data! Object: %1").arg(_id) );
602  return;
603  }
604 
605  // ================================================================================
606  // Check for requested Texture
607  // ================================================================================
608  if ( !texData->textureExists(_textureName) ) {
609  emit log(LOGERR, "slotTextureIndex: Texture not available! " + _textureName );
610  return;
611  }
612 
613  _index = texData->texture(_textureName).id();
614 }
615 
616 void TextureControlPlugin::slotTextureIndexPropertyName(int _id, QString& _propertyName) {
617 
618  // Get the object
619  BaseObjectData* obj;
620  if (! PluginFunctions::getObject( _id , obj ) ) {
621  emit log(LOGERR,"slotTextureIndexPropertyName: Unable to get Object for id " + QString::number(_id) );
622  return;
623  }
624 
625  // Get texture index property name
626  if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
627  _propertyName = PluginFunctions::triMeshObject(obj)->meshNode()->indexPropertyName().c_str();
628  } else if( obj->dataType( DATA_POLY_MESH ) ) {
629  _propertyName = PluginFunctions::polyMeshObject(obj)->meshNode()->indexPropertyName().c_str();
630  } else {
631  emit log(LOGERR,"slotTextureIndexPropertyName: Unable to access mesh for object with id " + QString::number(_id) );
632  }
633 }
634 
635 void TextureControlPlugin::slotTextureName( int _id, int _textureIndex, QString& _textureName){
636 
637  // Get the object
638  BaseObjectData* obj;
639  if (! PluginFunctions::getObject( _id , obj ) ) {
640  emit log(LOGERR,"slotTextureName: Unable to get Object for id " + QString::number(_id) );
641  }
642 
643  // ================================================================================
644  // Get Texture data for current object
645  // ================================================================================
646  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
647  if (texData == 0) {
648  emit log(LOGERR, tr("slotTextureName: Object has no texture data! Object: %1").arg(_id) );
649  return;
650  }
651 
652  for (uint i=0; i < texData->textures().size(); i++ )
653  if ( (texData->textures()[i]).id() == _textureIndex ){
654  _textureName = (texData->textures()[i]).name();
655  return;
656  }
657 
658  emit log(LOGERR, "slotTextureName: TextureIndex not available! (" + QString::number(_textureIndex) + ")" );
659  _textureName = "NOT_FOUND";
660  return;
661 }
662 
663 void TextureControlPlugin::slotTextureFilename( int _id, QString _textureName, QString& _textureFilename){
664 
665  // Get the object
666  BaseObjectData* obj;
667  if (! PluginFunctions::getObject( _id , obj ) ) {
668  emit log(LOGERR,"slotTextureFilename: Unable to get Object for id " + QString::number(_id) );
669  }
670 
671  // ================================================================================
672  // Get Texture data for current object
673  // ================================================================================
674  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
675  if (texData == 0) {
676  emit log(LOGERR, tr("slotTextureFilename: Object has no texture data! Object: %1").arg(_id) );
677  return;
678  }
679 
680  // Search in local textures
681  for (uint i=0; i < texData->textures().size(); i++ ) {
682  for (int j=0; j < texData->textures()[i].multiTextureList.size(); j++ ) {
683  if ( (texData->textures()[i]).name() == _textureName ){
684  Texture& tex = texData->texture((texData->textures()[i]).name());
685  _textureFilename = tex.filename();
686  return;
687  } else if ( (texData->textures()[i]).multiTextureList[j] == _textureName ){
688  Texture& tex = texData->texture((texData->textures()[i]).multiTextureList[j]);
689  _textureFilename = tex.filename();
690  return;
691  }
692  }
693  }
694 
695  _textureFilename = OpenFlipper::Options::textureDir().path() +
696  QDir::separator().toLatin1() + (globalTextures_.texture(_textureName)).filename();
697 
698  QFile f(_textureFilename);
699  if(!f.exists()) _textureFilename = "NOT_FOUND";
700 
701  return;
702 }
703 
704 void TextureControlPlugin::slotGetCurrentTexture( int _id, QString& _textureName ){
705 
706  _textureName = "NONE";
707 
708  // Get the object
709  BaseObjectData* obj;
710  if (! PluginFunctions::getObject( _id , obj ) ) {
711  emit log(LOGERR,"slotGetCurrentTexture: Unable to get Object for id " + QString::number(_id) );
712  }
713 
714  // ================================================================================
715  // Get Texture data for current object
716  // ================================================================================
717  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
718  if (texData == 0) {
719  #ifndef NDEBUG
720 
721  // Iterate over all per Object datas and output them
722  QMap<QString, PerObjectData*>::const_iterator mapIter = obj->getPerObjectDataMap().begin();
723  while ( mapIter != obj->getPerObjectDataMap().end() ) {
724  ++mapIter;
725  }
726  #endif
727 
728  return;
729  }
730 
731  // Iterate over all available textures
732  for ( uint i = 0 ; i < texData->textures().size() ; ++i) {
733 
734  if ( (texData->textures()[i]).enabled() ){
735  _textureName = (texData->textures()[i]).name();
736 
737  if ( (texData->textures()[i]).type() == MULTITEXTURE ) {
738  return;
739  }
740  }
741  }
742 }
743 
744 void TextureControlPlugin::slotGetSubTextures( int _id, QString _multiTextureName, QStringList& _subTextures ){
745  // Get the object
746  BaseObjectData* obj;
747  if (! PluginFunctions::getObject( _id , obj ) ) {
748  emit log(LOGERR,"slotGetSubTextures: Unable to get Object for id " + QString::number(_id) );
749  }
750 
751  // ================================================================================
752  // Get Texture data for current object
753  // ================================================================================
754  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
755  if (texData == 0) {
756  emit log(LOGERR, tr("slotGetSubTextures: Object has no texture data! Object: %1").arg(_id) );
757  return;
758  }
759 
760  // ================================================================================
761  // Check for requested Texture
762  // ================================================================================
763  if ( !texData->textureExists(_multiTextureName) ) {
764  emit log(LOGERR, "slotGetSubTextures: Texture not available! " + _multiTextureName );
765  return;
766  }
767 
768  if ( texData->texture(_multiTextureName).type() == MULTITEXTURE )
769  _subTextures = texData->texture(_multiTextureName).multiTextureList;
770  else
771  _subTextures = QStringList();
772 }
773 
774 void TextureControlPlugin::slotTextureUpdated( QString _textureName , int _identifier ){
775 
776  // ================================================================================
777  // Get updated object
778  // ================================================================================
779  BaseObjectData* obj;
780  if (! PluginFunctions::getObject( _identifier , obj ) ) {
781  emit log(LOGERR,"slotTextureUpdated: Unable to get Object for id " + QString::number(_identifier) );
782  return;
783  }
784 
785  //skip object if its not a mesh
786  if( !obj->dataType( DATA_TRIANGLE_MESH ) && !obj->dataType( DATA_POLY_MESH )
787 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
788  && !obj->dataType( DATA_HEXAHEDRAL_MESH )
789 #endif
790 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
791  && !obj->dataType( DATA_POLYHEDRAL_MESH )
792 #endif
793 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
795 #endif
796  )
797  return;
798 
799  // ================================================================================
800  // Get objects texture data and verify that texture exists
801  // ================================================================================
802  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
803  if (texData == 0){
804  emit log(LOGERR,tr("slotTextureUpdated: Texture data not found: Object %1" ).arg(_identifier) );
805  return;
806  }
807 
808  // ================================================================================
809  // Check if texture exists
810  // ================================================================================
811  if ( ! texData->textureExists(_textureName) ) {
812  emit log(LOGERR,"slotTextureUpdated: Texture " + _textureName + " not found on object " + QString::number(_identifier) );
813  return;
814  }
815 
816  // ================================================================================
817  // If texture is not enabled, mark it as dirty and defer update to visualization update
818  // ================================================================================
819  if ( ! texData->texture(_textureName).enabled() ) {
820  texData->texture(_textureName).setDirty();
821  return;
822  }
823 
824  // ================================================================================
825  // Enable the texture in texture node
826  // ================================================================================
827  if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
828  TriMesh* mesh = PluginFunctions::triMesh(obj);
829  doUpdateTexture(texData->texture(_textureName), *mesh);
830  // Texture has been bound to that object by slotAddTexture.. directly or by fileOpened from global texture
831  // Just activate it
832  PluginFunctions::triMeshObject(obj)->textureNode()->activateTexture(texData->texture(_textureName).glName() );
833  PluginFunctions::triMeshObject(obj)->textureNode()->set_repeat(texData->texture(_textureName).parameters.repeat);
834  } else if ( obj->dataType( DATA_POLY_MESH ) ) {
835  PolyMesh* mesh = PluginFunctions::polyMesh(obj);
836  doUpdateTexture(texData->texture(_textureName), *mesh);
837  // Texture has been bound to that object by slotAddTexture.. directly or by fileOpened from global texture
838  // Just activate it
839  PluginFunctions::polyMeshObject(obj)->textureNode()->activateTexture(texData->texture(_textureName).glName() );
840  PluginFunctions::polyMeshObject(obj)->textureNode()->set_repeat(texData->texture(_textureName).parameters.repeat);
841  }
842 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
843  else if ( obj->dataType( DATA_HEXAHEDRAL_MESH ) ) {
846  doUpdateTextureOVM(texData->texture(_textureName), *mesh, *meshObj);
847  // Texture has been bound to that object by slotAddTexture.. directly or by fileOpened from global texture
848  // Just activate it
849  PluginFunctions::hexahedralMeshObject(obj)->textureNode()->activateTexture(texData->texture(_textureName).glName() );
850  PluginFunctions::hexahedralMeshObject(obj)->textureNode()->set_repeat(texData->texture(_textureName).parameters.repeat);
851  }
852 #endif
853 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
854  else if ( obj->dataType( DATA_POLYHEDRAL_MESH ) ) {
857  doUpdateTextureOVM(texData->texture(_textureName), *mesh, *meshObj);
858  // Texture has been bound to that object by slotAddTexture.. directly or by fileOpened from global texture
859  // Just activate it
860  PluginFunctions::polyhedralMeshObject(obj)->textureNode()->activateTexture(texData->texture(_textureName).glName() );
861  PluginFunctions::polyhedralMeshObject(obj)->textureNode()->set_repeat(texData->texture(_textureName).parameters.repeat);
862  }
863 #endif
864 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
865  else if (obj->dataType(DATA_BSPLINE_SURFACE)) {
866  // texcoords are parametric so nothing to update in the bspline surface mesh
867  // Texture has been bound to that object by slotAddTexture.. directly or by fileOpened from global texture
868  // Just activate it
869  PluginFunctions::bsplineSurfaceObject(obj)->textureNode()->activateTexture(texData->texture(_textureName).glName());
870  PluginFunctions::bsplineSurfaceObject(obj)->textureNode()->set_repeat(texData->texture(_textureName).parameters.repeat);
871  }
872 #endif
873 
874  // ================================================================================
875  // Mark texture as not dirty
876  // ================================================================================
877  texData->texture(_textureName).clean();
878 
879  // ================================================================================
880  // Tell plugins to update texture
881  // ================================================================================
882  emit updatedObject(obj->id(),UPDATE_TEXTURE);
883 
884 }
885 
886 void TextureControlPlugin::slotUpdateTexture( QString _textureName , int _identifier) {
887  if ( _textureName == "Reflection Lines" )
888  slotTextureUpdated( _textureName , _identifier );
889 
890 }
891 
892 template< typename MeshT >
893 void TextureControlPlugin::doUpdateTexture ( Texture& _texture, MeshT& _mesh )
894 {
895 
896  if ( _texture.type() == HALFEDGEBASED ) {
897  if (_texture.dimension() == 1) {
898 
900  if ( ! _mesh.get_property_handle(texture, _texture.name().toStdString() ) ) {
901  emit log(LOGERR,tr("doUpdateTexture: HALFEDGEBASED dimension 1: Unable to get property %1").arg(_texture.name()) );
902  return;
903  }
904 
905  copyTexture(_texture, _mesh, texture);
906 
907  } else if ( _texture.dimension() == 2 ) {
908 
910  if ( ! _mesh.get_property_handle( texture2D, _texture.name().toStdString() ) ) {
911  emit log(LOGERR,tr("doUpdateTexture: HALFEDGEBASED dimension 2: Unable to get property %1").arg(_texture.name()) );
912  return;
913  }
914 
915  copyTexture( _texture, _mesh, texture2D);
916 
917  } else
918  emit log(LOGERR, "doUpdateTexture: Unsupported Texture Dimension " + QString::number(_texture.dimension() ) );
919  } else if ( _texture.type() == VERTEXBASED ) {
920  if ( _texture.dimension() == 1 ) {
921 
923  if ( ! _mesh.get_property_handle(texture,_texture.name().toStdString() ) ) {
924  emit log(LOGERR,tr("doUpdateTexture: VERTEXBASED dimension 1: Unable to get property %1").arg(_texture.name()) );
925  return;
926  }
927 
928  copyTexture(_texture, _mesh, texture);
929 
930  } else if ( _texture.dimension() == 2 ) {
931 
933  if ( ! _mesh.get_property_handle(texture2D,_texture.name().toStdString() ) ) {
934  emit log(LOGERR,tr("doUpdateTexture: VERTEXBASED dimension 2: Unable to get property %1").arg(_texture.name()) );
935  return;
936  }
937 
938  copyTexture( _texture, _mesh, texture2D);
939 
940  } /*else if ( textures_[_textureid].dimension == 3 ) {
941 
942  OpenMesh::VPropHandleT< OpenMesh::Vec3d > scalarField3D;
943  if ( ! _mesh.get_property_handle(scalarField3D,_texture.name) ) {
944  emit log(LOGERR,"Unable to get property " + _texture.name );
945  return;
946  }
947 
948  copyTexture(_textureid, _mesh, scalarField3D);
949 
950  }*/ else
951  emit log(LOGERR, "doUpdateTexture: Unsupported Texture Dimension " + QString::number(_texture.dimension() ) );
952 
953  } else
954  emit log(LOGERR, "doUpdateTexture: Unsupported Texture type");
955 
956 }
957 
958 
959 #ifdef ENABLE_OPENVOLUMEMESH_SUPPORT
960 template< typename VolumeMeshT, typename VolumeMeshObjectT >
961 void TextureControlPlugin::doUpdateTextureOVM ( Texture& _texture, VolumeMeshT& _mesh, VolumeMeshObjectT& _obj )
962 {
963  if ( _texture.type() == VERTEXBASED ) {
964  if ( _texture.dimension() == 1 ) {
965 
966  if (!_mesh.template vertex_property_exists<double>(_texture.name().toStdString())){
967  emit log(LOGERR,tr("doUpdateTexture: VERTEXBASED dimension 1: Unable to get property %1").arg(_texture.name()) );
968  return;
969  }
970 
971  OpenVolumeMesh::VertexPropertyT< double > texture = _mesh.template request_vertex_property<double>(_texture.name().toStdString());
972  copyTexture(_texture, _mesh, _obj, texture);
973 
974  VolumeMeshDrawModesContainer drawModesVolumeMesh;
975  _obj.setObjectDrawMode(drawModesVolumeMesh.facesTextured);
976 
977  }
978  else if ( _texture.dimension() == 2 )
979  {
980 
981  if (!_mesh.template vertex_property_exists<ACG::Vec2d>(_texture.name().toStdString())){
982  emit log(LOGERR,tr("doUpdateTexture: VERTEXBASED dimension 2: Unable to get property %1").arg(_texture.name()) );
983  return;
984  }
985  OpenVolumeMesh::VertexPropertyT< ACG::Vec2d > texture = _mesh.template request_vertex_property<ACG::Vec2d>(_texture.name().toStdString());
986  copyTexture(_texture, _mesh, _obj, texture);
987 
988  VolumeMeshDrawModesContainer drawModesVolumeMesh;
989  _obj.setObjectDrawMode(drawModesVolumeMesh.facesTextured);
990 
991  }
992  else
993  emit log(LOGERR, "doUpdateTexture: Unsupported Texture Dimension " + QString::number(_texture.dimension() ) );
994 
995  } else
996  emit log(LOGERR, "doUpdateTexture: Unsupported Texture type");
997 
998 }
999 #endif
1000 
1001 void TextureControlPlugin::slotDrawModeChanged(int _viewerId ) {
1002 
1003 #ifdef ENABLE_OPENVLUMEMESH_SUPPORT
1004  VolumeMeshDrawModesContainer drawModesVolumeMesh;
1005 #endif
1006 
1007  // Only update if we have a relevant draw mode
1012 
1013 #ifdef ENABLE_OPENVLUMEMESH_SUPPORT
1014  ||
1015  ( PluginFunctions::drawMode(_viewerId) &= drawModesVolumeMesh.facesTextured) ||
1016  ( PluginFunctions::drawMode(_viewerId) &= drawModesVolumeMesh.facesTexturedShaded)
1017 #endif
1018  )) {
1019  return;
1020  }
1021 
1022  // Iterate over all Objects
1024  o_it != PluginFunctions::objectsEnd();
1025  ++o_it) {
1026 
1027  // Get the corresponding texture data
1028  TextureData* texData = dynamic_cast< TextureData* > ( o_it->objectData(TEXTUREDATA) );
1029  if (texData == 0){
1030  continue;
1031  }
1032 
1033  // Go over all textures and if one of them is enabled and dirty, update it here
1034  for ( uint i = 0; i < texData->textures().size(); ++i ) {
1035  if ( texData->textures()[i].enabled() && texData->textures()[i].dirty() ) {
1036  emit updateTexture( texData->textures()[i].name() , o_it->id() );
1037  }
1038  }
1039 
1040 
1041  }
1042 
1043  emit updateView();
1044 
1045 }
1046 
1047 void TextureControlPlugin::slotObjectUpdated(int _identifier, const UpdateType& _type)
1048 {
1049  if( !_type.contains(UPDATE_ALL) && !_type.contains(UPDATE_GEOMETRY) && !_type.contains(UPDATE_TOPOLOGY) )
1050  return;
1051 
1052  // ================================================================================
1053  // Get updated object
1054  // ================================================================================
1055  if ( _identifier == -1 )
1056  return;
1057 
1058  BaseObjectData* obj;
1059  if (! PluginFunctions::getObject( _identifier , obj ) )
1060  return;
1061 
1062  //skip object if its not a mesh
1063  if( !obj->dataType( DATA_TRIANGLE_MESH ) && !obj->dataType( DATA_POLY_MESH )
1064 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1065  && !obj->dataType( DATA_HEXAHEDRAL_MESH )
1066 #endif
1067 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1068  && !obj->dataType( DATA_POLYHEDRAL_MESH )
1069 #endif
1070 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
1071  && !obj->dataType(DATA_BSPLINE_SURFACE)
1072 #endif
1073  )
1074  return;
1075 
1076  // ================================================================================
1077  // Get objects texture data and verify that texture exists
1078  // ================================================================================
1079  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
1080  if (texData == 0){
1081  return;
1082  }
1083 
1084  // ================================================================================
1085  // Set all textures to dirty
1086  // ================================================================================
1087  // TODO : if not in the texture rendering mode, do not emit update
1088  // Involves adding a interface part to react on draw mode changes
1089  // basic check implemented
1090  for ( uint i = 0; i < texData->textures().size(); ++i ) {
1091  texData->textures()[i].setDirty();
1092 
1093  bool update = false;
1094  for ( int j = 0 ; j < PluginFunctions::viewers() ; ++j ) {
1099 
1100 #ifdef ENABLE_OPENVOLUMEMESH_SUPPORT
1101  VolumeMeshDrawModesContainer ovmDrawModes;
1102  update |= ( PluginFunctions::drawMode(j) &= ovmDrawModes.facesTextured );
1103  update |= ( PluginFunctions::drawMode(j) &= ovmDrawModes.facesTexturedShaded );
1104 #endif
1105  }
1106 
1107  if ( update && texData->textures()[i].enabled() )
1108  emit updateTexture( texData->textures()[i].name() , _identifier );
1109  }
1110 
1111 }
1112 
1113 void TextureControlPlugin::slotUpdateAllTextures( ) {
1114  std::cerr << "slotUpdateAllTextures: not implemented yet ... might be removed" << std::endl;
1115  // TODO : Check
1116 // // Force an update of all textures which are available for the updated object
1117 // for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS) ; o_it != PluginFunctions::objectsEnd(); ++o_it)
1118 // for ( uint i = 0 ; i < textures_.size() ; ++i )
1119 // emit updateTexture( textures_[i].name , o_it->id() );
1120 }
1121 
1122 bool TextureControlPlugin::parseMode( QString _mode, Texture& _texture ) {
1123 
1124  bool changed = false;
1125 
1126  int i = 0;
1127  QString nextString = _mode.section(',',i,i);
1128  while ( nextString != "" ) {
1129  QString sectionName = nextString.section('=',0,0);
1130  QString value = nextString.section('=',1,1);
1131 
1132  // Cleanup representation
1133  value = value.trimmed();
1134  sectionName = sectionName.trimmed();
1135  sectionName = sectionName.toLower();
1136 
1137  if ( sectionName == "clamp" ) {
1138  if ( StringToBool(value) != _texture.parameters.clamp ) {
1139  _texture.parameters.clamp = StringToBool(value);
1140  changed = true;
1141  }
1142  } else if ( sectionName == "clamp_max" ) {
1143  if (value.toDouble() != _texture.parameters.clampMax){
1144  _texture.parameters.clampMax = value.toDouble();
1145  changed = true;
1146  }
1147  } else if ( sectionName == "clamp_min" ) {
1148  if (value.toDouble() != _texture.parameters.clampMin){
1149  _texture.parameters.clampMin = value.toDouble();
1150  changed = true;
1151  }
1152  } else if ( sectionName == "max_val" ) {
1153  if (value.toDouble() != _texture.parameters.repeatMax){
1154  _texture.parameters.repeatMax = value.toDouble();
1155  changed = true;
1156  }
1157  } else if ( sectionName == "min_val" ) {
1158  if (value.toDouble() != _texture.parameters.repeatMin){
1159  _texture.parameters.repeatMin = value.toDouble();
1160  changed = true;
1161  }
1162  } else if ( sectionName == "repeat" ) {
1163  if ( StringToBool(value) != _texture.parameters.repeat ) {
1164  _texture.parameters.repeat = StringToBool(value);
1165  changed = true;
1166  }
1167  } else if ( sectionName == "center" ) {
1168  if ( StringToBool(value) != _texture.parameters.center ) {
1169  _texture.parameters.center = StringToBool(value);
1170  changed = true;
1171  }
1172  } else if ( sectionName == "scale" ) {
1173  if ( StringToBool(value) != _texture.parameters.scale ) {
1174  _texture.parameters.scale = StringToBool(value);
1175  changed = true;
1176  }
1177  } else if ( sectionName == "abs" ) {
1178  if ( StringToBool(value) != _texture.parameters.abs ) {
1179  _texture.parameters.abs = StringToBool(value);
1180  changed = true;
1181  }
1182  } else if ( sectionName == "indexproperty" ) {
1183  if ( value != _texture.indexMappingProperty() ) {
1184  _texture.indexMappingProperty( value );
1185  changed = true;
1186  }
1187  } else if ( sectionName == "visiblename" ) {
1188  if ( value != _texture.visibleName() ) {
1189  _texture.visibleName( value );
1190  changed = true;
1191  }
1192  } else if ( sectionName == "type" ) {
1193  if ( ( value == "halfedgebased" ) && ( _texture.type() != HALFEDGEBASED ) ) {
1194  _texture.type( HALFEDGEBASED );
1195  changed = true;
1196  } else if ( (value == "vertexbased") && (_texture.type() != HALFEDGEBASED) ) {
1197  _texture.type( VERTEXBASED );
1198  changed = true;
1199  } else if ( (value == "environmentmap") && (_texture.type() != ENVIRONMENT) ) {
1200  _texture.type( ENVIRONMENT );
1201  changed = true;
1202  } else {
1203  emit log(LOGERR,"parseMode: Unknown texture type : " + value + " for texture: " + _texture.name() );
1204  }
1205  } else
1206  emit log(LOGERR,"parseMode: Unknown texture mode : " + sectionName);
1207 
1208  ++i;
1209  nextString = _mode.section(',',i,i);
1210  }
1211 
1212  return changed;
1213 }
1214 
1215 void TextureControlPlugin::slotSetTextureMode(QString _textureName ,QString _mode) {
1216 
1217  // ================================================================================
1218  // Update texture settings for global textures
1219  // ================================================================================
1220  if ( ! globalTextures_.textureExists(_textureName) ) {
1221  emit log(LOGERR,"slotSetTextureMode: Global texture does not exist: " + _textureName);
1222  return;
1223  }
1224 
1225  // ================================================================================
1226  // Parse parameters and update them in the texture data
1227  // ================================================================================
1228  Texture& texture = globalTextures_.texture(_textureName);
1229 
1230  // Parse the mode settings
1231  parseMode(_mode,texture);
1232  _mode = _mode.toLower();
1233 
1234  // ================================================================================
1235  // Mark updated texture as dirty
1236  // ================================================================================
1237  texture.setDirty();
1238 
1239 
1240  // check if the local textures need to be updated
1242 
1243  TextureData* texData = dynamic_cast< TextureData* > ( o_it->objectData(TEXTUREDATA) );
1244 
1245  if (texData != 0){
1246 
1247  if ( texData->textureExists(_textureName) ){
1248 
1249  Texture& localTex = texData->texture(_textureName);
1250 
1251  //check if something changed
1252  bool changed = false;
1253 
1254  if ( _mode.contains("clamp") && (texture.parameters.clamp != localTex.parameters.clamp) ){
1255  localTex.parameters.clamp = texture.parameters.clamp;
1256  changed = true;
1257  }
1258 
1259  if ( _mode.contains("clamp_max") && (texture.parameters.clampMax != localTex.parameters.clampMax) ){
1260  localTex.parameters.clampMax = texture.parameters.clampMax;
1261  changed = true;
1262  }
1263 
1264  if ( _mode.contains("clamp_min") && (texture.parameters.clampMin != localTex.parameters.clampMin) ){
1265  localTex.parameters.clampMin = texture.parameters.clampMin;
1266  changed = true;
1267  }
1268 
1269  if ( _mode.contains("max_val") && (texture.parameters.repeatMax != localTex.parameters.repeatMax) ){
1270  localTex.parameters.repeatMax = texture.parameters.repeatMax;
1271  changed = true;
1272  }
1273 
1274  if ( _mode.contains("min_val") && (texture.parameters.repeatMin != localTex.parameters.repeatMin) ){
1275  localTex.parameters.repeatMin = texture.parameters.repeatMin;
1276  changed = true;
1277  }
1278 
1279  if ( _mode.contains("repeat") && (texture.parameters.repeat != localTex.parameters.repeat) ){
1280  localTex.parameters.repeat = texture.parameters.repeat;
1281  changed = true;
1282  }
1283 
1284  if ( _mode.contains("center") && (texture.parameters.center != localTex.parameters.center) ){
1285  localTex.parameters.center = texture.parameters.center;
1286  changed = true;
1287  }
1288 
1289  if ( _mode.contains("scale") && (texture.parameters.scale != localTex.parameters.scale) ){
1290  localTex.parameters.scale = texture.parameters.scale;
1291  changed = true;
1292  }
1293 
1294  if ( _mode.contains("type") && (texture.type() != localTex.type() ) ){
1295  localTex.type( texture.type() );
1296  changed = true;
1297  }
1298 
1299  if ( _mode.contains("visiblename") && (texture.visibleName() != localTex.visibleName() ) ){
1300  localTex.visibleName( texture.visibleName() );
1301  changed = true;
1302  }
1303 
1304  //only update if the texture is enabled
1305  if (changed){
1306  if ( texData->isEnabled(_textureName) )
1307  emit updateTexture( _textureName, o_it->id() );
1308  else
1309  localTex.setDirty();
1310  }
1311  }
1312  }
1313  }
1314 }
1315 
1316 bool TextureControlPlugin::StringToBool(QString _value){
1317  if (_value == "false")
1318  return false;
1319  else
1320  return true;
1321 }
1322 
1323 void TextureControlPlugin::slotSetTextureMode(QString _textureName, QString _mode, int _id) {
1324 
1325  // Get the new object
1326  BaseObjectData* obj;
1327  if (! PluginFunctions::getObject( _id , obj ) ) {
1328  emit log(LOGERR,"slotSetTextureMode: Unable to get Object for id " + QString::number(_id) );
1329  }
1330 
1331  // Get Texture data for this object
1332  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
1333 
1334  if ( texData == 0 || ( !texData->textureExists(_textureName)) ) {
1335  emit log(LOGERR,"slotSetTextureMode: Texture does not exist: " + _textureName + " (object=" + QString::number(_id) + ")");
1336  return;
1337  }
1338 
1339  // ================================================================================
1340  // Parse parameters and update them in the texture data
1341  // ================================================================================
1342  Texture& texture = texData->texture(_textureName);
1343 
1344 
1345  bool changed = parseMode(_mode,texture);
1346 
1347  //only update if the texture is enabled
1348  if (changed){
1349  if ( texData->isEnabled(_textureName) )
1350  emit updateTexture( _textureName, _id );
1351  else
1352  texture.setDirty();
1353  }
1354 }
1355 
1356 void TextureControlPlugin::pluginsInitialized() {
1357  // ================================================================================
1358  // Create global texture menu
1359  // ================================================================================
1360  textureMenu_ = new QMenu(tr("&Texture Control"));
1361  textureMenu_->setTearOffEnabled(true);
1362  emit addMenubarAction(textureMenu_->menuAction(), VIEWMENU );
1363 
1364  // ================================================================================
1365  // Create Settings dialog
1366  // ================================================================================
1367  // TODO : Settings dialog updates required to change global/local textures,...
1368  settingsDialog_ = new texturePropertiesWidget(0);
1369  connect( settingsDialog_, SIGNAL( applyProperties(TextureData*,QString,int) ),
1370  this, SLOT( applyDialogSettings(TextureData*,QString,int) ));
1371 
1372  connect( settingsDialog_, SIGNAL( getCoordinates1D(QString,int,std::vector< double >&)),
1373  this, SLOT( getCoordinates1D(QString,int,std::vector< double >&)));
1374 
1375  settingsDialog_->installEventFilter( this );
1376 
1377  // ================================================================================
1378  // Create action group and menu for global textures
1379  // ================================================================================
1380  actionGroup_ = new QActionGroup( 0 );
1381  actionGroup_->setExclusive( true );
1382  connect( actionGroup_, SIGNAL( triggered( QAction * ) ),
1383  this, SLOT( slotTextureMenu( QAction * ) ) );
1384 
1385  QAction* AC_Texture_Settings = new QAction(tr("&Texture Settings"), this);
1386  AC_Texture_Settings->setStatusTip(tr("Set the texture visualization properties"));
1387  connect(AC_Texture_Settings, SIGNAL(triggered()), this, SLOT(slotSetTextureProperties()));
1388  textureMenu_->addAction(AC_Texture_Settings);
1389 
1390  textureMenu_->addSeparator();
1391  textureMenu_->addActions(actionGroup_->actions());
1392 
1393  // ================================================================================
1394  // Create basic per object context menu
1395  // ================================================================================
1396  contextMenu_ = new QMenu(0);
1397  contextMenu_->setTitle("Textures");
1398  emit addContextMenuItem(contextMenu_->menuAction() ,DATA_TRIANGLE_MESH , CONTEXTOBJECTMENU );
1399  emit addContextMenuItem(contextMenu_->menuAction() ,DATA_POLY_MESH , CONTEXTOBJECTMENU );
1400 
1401 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1402  emit addContextMenuItem(contextMenu_->menuAction() ,DATA_HEXAHEDRAL_MESH , CONTEXTOBJECTMENU );
1403 #endif
1404 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1405  emit addContextMenuItem(contextMenu_->menuAction() ,DATA_POLYHEDRAL_MESH , CONTEXTOBJECTMENU );
1406 #endif
1407 
1408 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
1409  emit addContextMenuItem(contextMenu_->menuAction(), DATA_BSPLINE_SURFACE, CONTEXTOBJECTMENU);
1410 #endif
1411 
1412  slotTextureAdded("Reflection Lines","reflection_map.png",2);
1413  slotSetTextureMode("Reflection Lines","type=environmentmap");
1414 }
1415 
1417 
1418  settingsDialog_->show( &globalTextures_, -1);
1419 }
1420 
1421 void TextureControlPlugin::applyDialogSettings(TextureData* _texData, QString _textureName, int _id) {
1422 
1423  if (_id != -1)
1424  {
1425  //local texture
1426 
1427  // Get the object
1428  BaseObjectData* obj;
1429  if (! PluginFunctions::getObject( _id , obj ) ) {
1430  emit log(LOGERR,"applyDialogSettings: Unable to get Object for id " + QString::number(_id) );
1431  }
1432 
1433  if ( !_texData->textureExists(_textureName) ) {
1434  emit log(LOGERR,"applyDialogSettings: Texture does not exist in applyDialogSettings " + _textureName );
1435  }
1436 
1437  Texture& texture = _texData->texture(_textureName );
1438 
1439  if( obj->dataType( DATA_TRIANGLE_MESH ) ){
1440  PluginFunctions::triMeshObject(obj)->textureNode()->set_texture(imageStore().getImage(texture.textureImageId(),0) , texture.glName() );
1441  } else if ( obj->dataType( DATA_POLY_MESH ) ) {
1442  PluginFunctions::polyMeshObject(obj)->textureNode()->set_texture(imageStore().getImage(texture.textureImageId(),0) , texture.glName() );
1443  }
1444 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1445  else if( obj->dataType( DATA_HEXAHEDRAL_MESH ) ){
1446  PluginFunctions::hexahedralMeshObject(obj)->textureNode()->set_texture(imageStore().getImage(texture.textureImageId(),0) , texture.glName() );
1447  }
1448 #endif
1449 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1450  else if ( obj->dataType( DATA_POLYHEDRAL_MESH ) ) {
1451  PluginFunctions::polyhedralMeshObject(obj)->textureNode()->set_texture(imageStore().getImage(texture.textureImageId(),0) , texture.glName() );
1452  }
1453 #endif
1454 
1455 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
1456  else if (obj->dataType(DATA_BSPLINE_SURFACE)) {
1457  PluginFunctions::bsplineSurfaceObject(obj)->textureNode()->set_texture(imageStore().getImage(texture.textureImageId(), 0), texture.glName());
1458  }
1459 #endif
1460 
1461  // Always mark texture as dirty
1462  _texData->texture( _textureName ).setDirty();
1463 
1464 
1465  //switch back to the active texture to force rebind
1466  for ( uint i=0; i < _texData->textures().size(); i++ )
1467  if ( _texData->textures()[i].enabled() ){
1468  doSwitchTexture( _texData->textures()[i].name(), _id);
1469  break;
1470  }
1471 
1472  emit updateView();
1473 
1474  }
1475  else
1476  {
1477  // global texture
1478 
1479  _texData->texture( _textureName ).setDirty();
1480 
1481  Texture& globalTexture = _texData->texture(_textureName);
1482 
1483  // check if the local textures need to be updated
1485 
1486  TextureData* texData = dynamic_cast< TextureData* > ( o_it->objectData(TEXTUREDATA) );
1487 
1488  if ( texData != 0 && texData->textureExists(_textureName) ){
1489 
1490  //overwrite local parameters
1491  Texture& localTexture = texData->texture(_textureName);
1492 
1493  bool changed = false;
1494 
1495  if (localTexture.parameters.clamp != globalTexture.parameters.clamp){
1496  localTexture.parameters.clamp = globalTexture.parameters.clamp;
1497  changed = true;
1498  }
1499  if (localTexture.parameters.clampMax != globalTexture.parameters.clampMax){
1500  localTexture.parameters.clampMax = globalTexture.parameters.clampMax;
1501  changed = true;
1502  }
1503  if (localTexture.parameters.clampMin != globalTexture.parameters.clampMin){
1504  localTexture.parameters.clampMin = globalTexture.parameters.clampMin;
1505  changed = true;
1506  }
1507  if (localTexture.parameters.repeatMax != globalTexture.parameters.repeatMax){
1508  localTexture.parameters.repeatMax = globalTexture.parameters.repeatMax;
1509  changed = true;
1510  }
1511  if (localTexture.parameters.repeatMin != globalTexture.parameters.repeatMin){
1512  localTexture.parameters.repeatMin = globalTexture.parameters.repeatMin;
1513  changed = true;
1514  }
1515  if (localTexture.parameters.repeat != globalTexture.parameters.repeat){
1516  localTexture.parameters.repeat = globalTexture.parameters.repeat;
1517  changed = true;
1518  }
1519  if (localTexture.parameters.center != globalTexture.parameters.center){
1520  localTexture.parameters.center = globalTexture.parameters.center;
1521  changed = true;
1522  }
1523  if (localTexture.parameters.scale != globalTexture.parameters.scale){
1524  localTexture.parameters.scale = globalTexture.parameters.scale;
1525  changed = true;
1526  }
1527 
1528  // update if something has changed
1529  if ( changed ){
1530  if ( texData->isEnabled(_textureName) )
1531  slotTextureUpdated( _textureName , o_it->id() );
1532  else
1533  texData->texture( _textureName ).setDirty();
1534  }
1535  }
1536  }
1537  }
1538 }
1539 
1541  // call existing function to switch the texture
1542  slotSwitchTexture( _action->text() );
1543 
1544  // Switch to the corresponding draw mode
1546  o_it != PluginFunctions::objectsEnd();
1547  ++o_it) {
1548 
1549  TextureData* texData = dynamic_cast< TextureData* > ( o_it->objectData(TEXTUREDATA) );
1550 
1551  if (texData != 0) {
1552  switchDrawMode(texData->texture(_action->text()).type(), o_it->id());
1553  }
1554 
1555  }
1556 }
1557 
1558 void TextureControlPlugin::doSwitchTexture( QString _textureName , int _id ) {
1559 
1560  // Get the new object
1561  BaseObjectData* obj;
1562  if (! PluginFunctions::getObject( _id , obj ) ) {
1563  emit log(LOGERR,"doSwitchTexture: Unable to get Object for id " + QString::number(_id) );
1564  }
1565 
1566  // Ignore light sources: ( TODO: Maybe use better detetion if textures are usefull )
1567  if ( obj->dataType(typeId("Light")) )
1568  return;
1569 
1570  // ================================================================================
1571  // Get Texture data for current object
1572  // ================================================================================
1573  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
1574  if (texData == 0) {
1575  emit log(LOGERR, tr("doSwitchTexture: Object has no texture data! Object: %1").arg(_id) );
1576  return;
1577  }
1578 
1579  // ================================================================================
1580  // Check for requested Texture
1581  // ================================================================================
1582  if ( !texData->textureExists(_textureName) ) {
1583  emit log(LOGERR, "doSwitchTexture: Texture not available! " + _textureName );
1584  return;
1585  }
1586 
1587  // ================================================================================
1588  // Check on texture types
1589  // ================================================================================
1590  QStringList textureList;
1591  switch (texData->texture(_textureName).type()) {
1592  // Handle MultiTextures first
1593  // Enable all textures of a multitexture block and disable all others
1594  case MULTITEXTURE:
1595  // get the list of textures for this mode
1596  textureList = texData->texture(_textureName).multiTextureList;
1597 
1598  texData->enableTexture(_textureName, true);
1599 
1600  for ( uint i = 0 ; i < texData->textures().size() ; ++i ) {
1601  if ( textureList.contains( texData->textures()[i].name() ) || (texData->textures()[i].name() == _textureName) )
1602  texData->enableTexture( texData->textures()[i].name() , false );
1603  else
1604  texData->disableTexture( texData->textures()[i].name() );
1605  }
1606  break;
1607  // These textures are working on mesh properties and need to be copied on access.
1608  // The actual drawing is performed if the plugin belonging to the texture updated it.
1609  // otherwise it will be directly enabled by this function
1610  case HALFEDGEBASED:
1611  case VERTEXBASED:
1612  // Enable the texture
1613  if ( ! texData->enableTexture( _textureName , true ) )
1614  emit log(LOGERR, "doSwitchTexture: Failed to enabled VERTEXBASED or HALFEDGEBASED Texture " + _textureName );
1615 
1616  // Check if dirty. If dirty, force plugin to update the texture otherwise we will copy it to our buffers and render it
1617  if ( texData->texture( _textureName).dirty() ) {
1618  // TODO: maybe introduce lock to prevent extra redraws if updating all objects
1619  emit updateTexture( texData->texture( _textureName ).name() , obj->id() );
1620  } else {
1621  // Copy the texture data to the global one
1622  if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
1623  doUpdateTexture(texData->texture(_textureName), *PluginFunctions::triMeshObject(obj)->mesh());
1624  } else if( obj->dataType( DATA_POLY_MESH ) ) {
1625  doUpdateTexture(texData->texture(_textureName), *PluginFunctions::polyMeshObject(obj)->mesh());
1626  }
1627 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1628  else if( obj->dataType( DATA_HEXAHEDRAL_MESH ) ) {
1631  doUpdateTextureOVM(texData->texture(_textureName), *mesh, *meshObj);
1632  }
1633 #endif
1634 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1635  else if( obj->dataType( DATA_POLYHEDRAL_MESH ) ) {
1638  doUpdateTextureOVM(texData->texture(_textureName), *mesh, *meshObj);
1639  }
1640 #endif
1641  else {
1642  emit log(LOGERR, "doSwitchTexture: HALFEDGEBASED or VERTEXBASED type require poly or trimesh to work! Texture: " + _textureName );
1643  }
1644  }
1645 
1646  break;
1647  // Environment textures are static for now so directly enable it without an update
1648  case ENVIRONMENT:
1649  if ( ! texData->enableTexture( _textureName , true ) ) {
1650  emit log(LOGERR, "doSwitchTexture: Failed to enabled ENVIRONMENT Texture " + _textureName );
1651  return;
1652  }
1653  break;
1654  case UNSET:
1655  emit log(LOGERR, "doSwitchTexture. Texture Type is unset! This should never happen! " + _textureName );
1656  break;
1657  }
1658 
1659  // ================================================================================
1660  // Update texture mappings and activate the textures
1661  // ================================================================================
1662  if ( texData->texture(_textureName).type() == MULTITEXTURE ) {
1663  if( obj->dataType( DATA_TRIANGLE_MESH ) ){
1664  // Set the property map for mapping between faces and textures
1665  PluginFunctions::triMeshObject(obj)->meshNode()->setIndexPropertyName( texData->texture( _textureName).indexMappingProperty().toStdString() );
1666  // Unbind all textures ( textures will be bound by textureNode later on
1668  // Set the mapping between texture ids in the index property and their gl Names
1670 
1671  if (PluginFunctions::triMeshObject(obj)->mesh()->has_halfedge_texcoords2D())
1673 
1674 
1675  } else if( obj->dataType( DATA_POLY_MESH ) ){
1676  // Set the property map for mapping between faces and textures
1677  PluginFunctions::polyMeshObject(obj)->meshNode()->setIndexPropertyName( texData->texture( _textureName).indexMappingProperty().toStdString() );
1678  // Unbind all textures ( textures will be bound by textureNode later on
1680  // Set the mapping between texture ids in the index property and their gl Names
1682 
1683  if (PluginFunctions::polyMeshObject(obj)->mesh()->has_halfedge_texcoords2D())
1685 
1686  } else {
1687  emit log(LOGERR, "doSwitchTexture: MultiTexture Error: Only supported on Tri or Poly Mesh for Texture: " + _textureName );
1688  }
1689  } else {
1690  if( obj->dataType( DATA_TRIANGLE_MESH ) ){
1691  // Activate the requested texture in texture node
1692  PluginFunctions::triMeshObject(obj)->textureNode()->activateTexture( texData->texture( _textureName ).glName() );
1693  // Disable the mapping properties ( only for multi texture mode )
1694  PluginFunctions::triMeshObject(obj)->meshNode()->setIndexPropertyName("No Texture Index");
1696 
1697  if ( texData->texture(_textureName).type() == HALFEDGEBASED ) {
1698  // We set it to the standard name here, as we copy user texture coordinates to the global representation
1700  } else {
1702  }
1703 
1704  } else if ( obj->dataType( DATA_POLY_MESH ) ){
1705  // Activate the requested texture in texture node
1706  PluginFunctions::polyMeshObject(obj)->textureNode()->activateTexture( texData->texture( _textureName ).glName() );
1707  // Disable the mapping properties ( only for multi texture mode )
1708  PluginFunctions::polyMeshObject(obj)->meshNode()->setIndexPropertyName("No Texture Index");
1710 
1711  if ( texData->texture(_textureName).type() == HALFEDGEBASED ) {
1712  // We set it to the standard name here, as we copy user texture coordinates to the global representation
1714  } else {
1716  }
1717 
1718  }
1719 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1720  else if ( obj->dataType( DATA_HEXAHEDRAL_MESH ) ){
1721  // Activate the requested texture in texture node
1722  PluginFunctions::hexahedralMeshObject(obj)->textureNode()->activateTexture( texData->texture( _textureName ).glName() );
1723  }
1724 #endif
1725 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
1726  else if ( obj->dataType( DATA_POLYHEDRAL_MESH ) ){
1727  // Activate the requested texture in texture node
1728  PluginFunctions::polyhedralMeshObject(obj)->textureNode()->activateTexture( texData->texture( _textureName ).glName() );
1729  }
1730 #endif
1731 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
1732  else if (obj->dataType(DATA_BSPLINE_SURFACE)){
1733  // Activate the requested texture in texture node
1734  PluginFunctions::bsplineSurfaceObject(obj)->textureNode()->activateTexture(texData->texture(_textureName).glName());
1735  }
1736 #endif
1737  else {
1738  emit log(LOGERR, "doSwitchTexture: Texture Error ( mesh required) for Texture: " + _textureName );
1739  }
1740  }
1741 
1742  emit updatedObject(obj->id(),UPDATE_TEXTURE);
1743 
1744 }
1745 
1746 void TextureControlPlugin::switchDrawMode( TextureType _type, int _id ) {
1747 
1748  // Get the new object
1749  BaseObjectData* obj;
1750  if (!PluginFunctions::getObject(_id, obj)) {
1751  emit log(LOGERR, "doSwitchTexture: Unable to get Object for id " + QString::number(_id));
1752  }
1753 
1754  switch (_type) {
1755  case MULTITEXTURE:
1756  case HALFEDGEBASED:
1758  break;
1759  case VERTEXBASED:
1760  obj->setObjectDrawMode(ACG::SceneGraph::DrawModes::SOLID_TEXTURED_SHADED, PluginFunctions::ALL_VIEWERS);
1761  break;
1762  case ENVIRONMENT:
1763  obj->setObjectDrawMode(ACG::SceneGraph::DrawModes::SOLID_ENV_MAPPED, PluginFunctions::ALL_VIEWERS);
1764  break;
1765  case UNSET:
1766  emit log(LOGERR, "doSwitchTexture: Switching drawmode for unknonw Texture Type!");
1767  break;
1768  }
1769 
1770  emit updateView();
1771 }
1772 
1773 void TextureControlPlugin::slotSwitchTexture( QString _textureName , int _id ) {
1774 
1775  doSwitchTexture(_textureName, _id);
1776 }
1777 
1778 void TextureControlPlugin::slotSwitchTexture( QString _textureName ) {
1779 
1781  o_it != PluginFunctions::objectsEnd();
1782  ++o_it)
1783 
1784  doSwitchTexture(_textureName, o_it->id() );
1785 
1786 }
1787 
1788 
1790 
1791  // ================================================================================
1792  // Get picking object object
1793  // ================================================================================
1794  if ( _objectId == -1 )
1795  return;
1796 
1797  BaseObjectData* obj;
1798  if (! PluginFunctions::getObject( _objectId , obj ) ) {
1799  emit log(LOGERR,"slotUpdateContextMenu: Unable to get Object for id " + QString::number(_objectId) );
1800  return;
1801  }
1802 
1803  //skip object if its not a mesh
1804  if( !obj->dataType( DATA_TRIANGLE_MESH ) && !obj->dataType( DATA_POLY_MESH )
1805 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1806  && !obj->dataType( DATA_HEXAHEDRAL_MESH )
1807 #endif
1808 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
1809  && !obj->dataType( DATA_POLYHEDRAL_MESH )
1810 #endif
1811 #ifdef ENABLE_BSPLINESURFACE_SUPPORT
1812  && !obj->dataType(DATA_BSPLINE_SURFACE)
1813 #endif
1814  )
1815  {
1816  contextMenu_->clear();
1817  return;
1818  }
1819 
1820  // ================================================================================
1821  // Get objects texture data and verify that texture exists
1822  // ================================================================================
1823  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
1824  if (texData == 0){
1825  emit log(LOGERR,tr("slotUpdateContextMenu: Texture data not found! Object %1 ").arg(_objectId) );
1826  return;
1827  }
1828 
1829  // ================================================================================
1830  // Prepare Texture menu
1831  // ================================================================================
1832  contextMenu_->clear();
1833  QActionGroup* actionGroup = new QActionGroup(0);
1834  actionGroup->setExclusive( true );
1835  connect( actionGroup, SIGNAL( triggered( QAction * ) ),
1836  this, SLOT( slotTextureContextMenu( QAction * ) ) );
1837 
1838  QAction* action = actionGroup->addAction( "Texture Settings" );
1839 
1840  contextMenu_->addAction( action );
1841  contextMenu_->addSeparator();
1842 
1843  for ( uint i = 0 ; i < texData->textures().size() ; ++i ) {
1844 
1845  if ( texData->textures()[i].hidden() )
1846  continue;
1847 
1848  if ( !texData->textures()[i].visibleName().isEmpty() )
1849  action = actionGroup->addAction( texData->textures()[i].visibleName() );
1850  else
1851  action = actionGroup->addAction( texData->textures()[i].name() );
1852 
1853  action->setCheckable(true);
1854 
1855  if ( texData->textures()[i].enabled() )
1856  action->setChecked(true);
1857 
1858  contextMenu_->addAction( action );
1859  }
1860 }
1861 
1862 
1864 
1865  // id of object for which the context menu is created, is stored in the action
1866  QVariant idVariant = _action->data( );
1867  int id = idVariant.toInt();
1868 
1869  // Get the object
1870  BaseObjectData* obj;
1871  if (! PluginFunctions::getObject( id , obj ) ) {
1872  emit log(LOGERR,"slotTextureContextMenu: Unable to get Object for id " + QString::number(id) );
1873  return;
1874  }
1875 
1876  // Get the corresponding texture data
1877  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
1878 
1879  if (_action->text() == "Texture Settings"){
1880 
1881  if (texData == 0){
1882 
1883  QMessageBox msgBox;
1884  msgBox.setText("Cannot show Properties. No Textures available!");
1885  msgBox.exec();
1886  return;
1887 
1888  } else {
1889  settingsDialog_->show( texData, id, obj->name() );
1890  }
1891 
1892  } else {
1893 
1894  if ( texData != 0) {
1895  slotSwitchTexture( _action->text() , id );
1896 
1897  // Switch to a texture drawMode
1898  switchDrawMode(texData->texture( _action->text() ).type(), id);
1899  }
1900  }
1901 
1902 }
1903 
1904 //compute histogram for the given texture property
1905 void TextureControlPlugin::getCoordinates1D(QString _textureName, int _id, std::vector< double >& _x ){
1906 
1907  // Get the new object
1908  BaseObjectData* obj;
1909  if (! PluginFunctions::getObject( _id , obj ) ) {
1910  emit log(LOGERR,"getCoordinates1D: Unable to get Object for id " + QString::number(_id) );
1911  }
1912 
1913  // ================================================================================
1914  // Get Texture data for current object
1915  // ================================================================================
1916  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
1917  if (texData == 0) {
1918  emit log(LOGERR,tr("getCoordinates1D: Object %1 has no texture data ").arg(_id) );
1919  return;
1920  }
1921 
1922  // ================================================================================
1923  // Check for requested Texture
1924  // ================================================================================
1925  if ( !texData->textureExists(_textureName) ) {
1926  emit log(LOGERR, "getCoordinates1D: Texture not available! " + _textureName );
1927  return;
1928  }
1929 
1930  if ( texData->texture( _textureName ).dirty() )
1931  emit updateTexture( _textureName , _id );
1932 
1933 
1934  // collect the 1d texture coords from vertex or halfedge porperty, depending on the texture type
1935  _x.clear();
1936 
1937  if( obj->dataType( DATA_TRIANGLE_MESH ) )
1938  {
1939  TriMesh* mesh = PluginFunctions::triMesh(obj);
1940 
1941  if ( texData->texture(_textureName).type() == VERTEXBASED )
1942  {
1944 
1945  if ( !mesh->get_property_handle(coordProp, _textureName.toStdString() ) )
1946  {
1947  emit log(LOGERR,tr("getCoordinates1D: Texture Property not found: Object %1 , TextureName %2").arg(_id).arg(_textureName) );
1948  return;
1949  }
1950 
1951  for ( TriMesh::VertexIter v_it = mesh->vertices_begin() ; v_it != mesh->vertices_end(); ++v_it)
1952  _x.push_back( mesh->property(coordProp,*v_it) );
1953 
1954  } // end of if vertex based for tri meshes
1955  else if ( texData->texture(_textureName).type() == HALFEDGEBASED )
1956  {
1958 
1959  if ( !mesh->get_property_handle(coordProp, _textureName.toStdString() ) )
1960  {
1961  emit log(LOGERR,tr("getCoordinates1D: Texture Property not found: Object %1 , TextureName %2").arg(_id).arg(_textureName) );
1962  return;
1963  }
1964 
1965  for ( TriMesh::HalfedgeIter h_it = mesh->halfedges_begin() ; h_it != mesh->halfedges_end(); ++h_it)
1966  _x.push_back( mesh->property(coordProp,*h_it) );
1967  } // end of if halfedge based for tri meshes
1968 
1969  } // end of if tri mesh
1970  else if ( obj->dataType( DATA_POLY_MESH ) )
1971  {
1972  PolyMesh* mesh = PluginFunctions::polyMesh(obj);
1973 
1974  if ( texData->texture(_textureName).type() == VERTEXBASED )
1975  {
1977 
1978  if ( !mesh->get_property_handle(coordProp, _textureName.toStdString() ) )
1979  {
1980  emit log(LOGERR,tr("getCoordinates1D: Texture Property not found: Object %1 , TextureName %2").arg(_id).arg(_textureName) );
1981  return;
1982  }
1983 
1984  for ( PolyMesh::VertexIter v_it = mesh->vertices_begin() ; v_it != mesh->vertices_end(); ++v_it)
1985  _x.push_back( mesh->property(coordProp,*v_it) );
1986  } // end of if vertex based for poly meshes
1987  else if ( texData->texture(_textureName).type() == HALFEDGEBASED )
1988  {
1990 
1991  if ( !mesh->get_property_handle(coordProp, _textureName.toStdString() ) )
1992  {
1993  emit log(LOGERR,tr("getCoordinates1D: Texture Property not found: Object %1 , TextureName %2").arg(_id).arg(_textureName) );
1994  return;
1995  }
1996 
1997  for ( PolyMesh::HalfedgeIter h_it = mesh->halfedges_begin() ; h_it != mesh->halfedges_end(); ++h_it)
1998  _x.push_back( mesh->property(coordProp,*h_it) );
1999  } // end of if halfedge based for poly meshes
2000  }// end of if poly mesh
2001 #ifdef ENABLE_OPENVOLUMEMESH_HEXAHEDRAL_SUPPORT
2002  else if ( obj->dataType( DATA_HEXAHEDRAL_MESH ) )
2003  {
2005 
2006  if ( texData->texture(_textureName).type() == VERTEXBASED )
2007  {
2008  if ( !mesh->vertex_property_exists<double>(_textureName.toStdString()) )
2009  {
2010  emit log(LOGERR,tr("getCoordinates1D: Texture Property not found: Object %1 , TextureName %2").arg(_id).arg(_textureName) );
2011  return;
2012  }
2013 
2014  OpenVolumeMesh::VertexPropertyT<double> coordProp = mesh->request_vertex_property<double>(_textureName.toStdString());
2015 
2016  for ( OpenVolumeMesh::VertexIter v_it = mesh->vertices_begin() ; v_it != mesh->vertices_end(); ++v_it)
2017  _x.push_back( coordProp[v_it] );
2018  }
2019  else
2020  {
2021  emit log(LOGERR,tr("getCoordinates1D: Only VERTEXBASED texture type supported for OpenVolumeMesh") );
2022  }
2023  }// end of if hexahedral mesh
2024 #endif
2025 #ifdef ENABLE_OPENVOLUMEMESH_POLYHEDRAL_SUPPORT
2026  else if ( obj->dataType( DATA_POLYHEDRAL_MESH ) )
2027  {
2029 
2030  if ( texData->texture(_textureName).type() == VERTEXBASED )
2031  {
2032 
2033  if ( !mesh->vertex_property_exists<double>(_textureName.toStdString()) )
2034  {
2035  emit log(LOGERR,tr("getCoordinates1D: Texture Property not found: Object %1 , TextureName %2").arg(_id).arg(_textureName) );
2036  return;
2037  }
2038 
2039  OpenVolumeMesh::VertexPropertyT<double> coordProp = mesh->request_vertex_property<double>(_textureName.toStdString());
2040 
2041  for ( OpenVolumeMesh::VertexIter v_it = mesh->vertices_begin() ; v_it != mesh->vertices_end(); ++v_it)
2042  _x.push_back( coordProp[v_it] );
2043  }
2044  else
2045  {
2046  emit log(LOGERR,tr("getCoordinates1D: Only VERTEXBASED texture type supported for OpenVolumeMesh") );
2047  }
2048  }// end of if polyhedral mesh
2049 #endif
2050 
2051 }
2052 
2053 void TextureControlPlugin::slotAboutToRestore( int _objectid ) {
2054 
2055  // ================================================================================
2056  // Get current object
2057  // ================================================================================
2058  BaseObjectData* obj;
2059  if (! PluginFunctions::getObject( _objectid , obj ) ) {
2060  emit log(LOGERR,"slotAboutToRestore: Unable to get Object for id " + QString::number(_objectid) );
2061  }
2062 
2063  // ================================================================================
2064  // Get Texture data for current object
2065  // ================================================================================
2066  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
2067  if (texData == 0) {
2068  // Nothing to do
2069  return;
2070  }
2071 
2072  // ================================================================================
2073  // Disable the Texture mapping in the current objects Meshnode
2074  // This will prevent the renderer to crash if the map is wrong after the restore
2075  // ================================================================================
2076  if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
2078  } else if ( obj->dataType( DATA_POLY_MESH ) ) {
2080  }
2081 
2082 }
2083 
2084 void TextureControlPlugin::slotRestored( int _objectid ) {
2085  // ================================================================================
2086  // Get the last active texture in the restored perObjectData
2087  // ================================================================================
2088  QString currentTexture;
2089  slotGetCurrentTexture(_objectid,currentTexture);
2090 
2091  // ================================================================================
2092  // Enable the last active texture
2093  // ================================================================================
2094  slotSwitchTexture(currentTexture,_objectid);
2095 }
2096 
2097 #if QT_VERSION < 0x050000
2098  Q_EXPORT_PLUGIN2( texturecontrolplugin , TextureControlPlugin );
2099 #endif
2100 
This class provides easy access to DrawModes supported by OpenVolumeMesh.
bool parseMode(QString _mode, Texture &_texture)
parse texture mode settings Parses the string _mode and changes the settings in _texture according to...
void slotUpdateContextMenu(int _objectId)
Slot from the context menu interface.
DLLEXPORT DataType typeId(QString _name)
Given a dataType Identifier string this function will return the id of the datatype.
Definition: Types.cc:150
std::map< int, GLuint > * textureMap()
Get pointer to the textureMap.
Definition: TextureData.cc:326
const UpdateType UPDATE_TEXTURE(UpdateTypeSet(1)<< 11)
Textures have changed.
QMap< QString, PerObjectData * > & getPerObjectDataMap()
get reference to map of all perObject Datas
Definition: BaseObject.cc:835
void setObjectDrawMode(const ACG::SceneGraph::DrawModes::DrawMode &_mode, const bool &_force=false)
Set the draw mode for the object.
const std::string & indexPropertyName() const
Get current texture index property name.
const UpdateType UPDATE_TOPOLOGY(UpdateTypeSet(1)<< 3)
Topology updated.
void doUpdateTexture(Texture &_texture, MeshT &_mesh)
Calls the correct copyTexture() function to copy the texture property into the displayed OM property...
bool getObject(int _identifier, BSplineCurveObject *&_object)
BSplineSurfaceObject * bsplineSurfaceObject(BaseObjectData *_object)
Cast an BaseObject to a BSplineSurfaceObject if possible.
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
The Menu will be shown when an object was picked.
DrawMode SOLID_2DTEXTURED_FACE
draw per halfedge textured faces
Definition: DrawModes.cc:102
#define DATA_POLYHEDRAL_MESH
int viewers()
Get the number of viewers.
bool isEnabled(QString _textureName)
Check if a texture is enabled.
Definition: TextureData.cc:105
int id() const
Definition: BaseObject.cc:201
const QStringList ALL_OBJECTS
Iterable object range.
DrawMode SOLID_2DTEXTURED_FACE_SHADED
draw per halfedge textured faces
Definition: DrawModes.cc:103
bool enableTexture(QString _textureName, bool _exclusive=false)
Enable a given texture.
Definition: TextureData.cc:122
void slotTextureMenu(QAction *_action)
Called when an action in the TextureMenu is triggered.
MeshT * mesh()
return a pointer to the mesh
Definition: MeshObjectT.cc:351
Texture & texture(QString _textureName)
Get the texture object.
Definition: TextureData.cc:277
Update type class.
Definition: UpdateType.hh:70
void setObjectData(QString _dataName, PerObjectData *_data)
Definition: BaseObject.cc:792
TexParameters parameters
Parameters of the texture.
Definition: TextureData.hh:144
PolyMeshObject * polyMeshObject(BaseObjectData *_object)
Cast an BaseObject to a PolyMeshObject if possible.
std::vector< Texture > & textures()
Get reference to the texture vector.
Definition: TextureData.cc:316
void copyTexture(Texture &_texture, MeshT &_mesh, OpenMesh::VPropHandleT< double > _texProp)
Copy the supplied 1D vertex property to both coordinates of the 2D vertex OM texture property...
bool activateTexture(GLuint _id)
Set active Texture.
Definition: TextureNode.cc:566
DrawMode SOLID_TEXTURED
draw textured faces
Definition: DrawModes.cc:94
Property classes for the different entity types.
#define DATA_HEXAHEDRAL_MESH
void slotSetTextureProperties()
Slot for showing the TextureProperties Dialog.
HexahedralMeshObject * hexahedralMeshObject(BaseObjectData *_object)
Cast an BaseObject to an HexahedralMeshObject if possible.
bool contains(const UpdateType &_type) const
Check if this update contains the given UpdateType.
Definition: UpdateType.cc:111
int addTexture(QString _textureName, QString _filename, uint _dimension, GLuint _glName)
Add a Texture.
Definition: TextureData.cc:164
ACG::SceneGraph::EnvMapNode * textureNode()
Get the TextureNode of the current mesh.
Definition: MeshObjectT.cc:549
void switchDrawMode(TextureType _type, int _id)
Checks for a correct drawmode and changes if necessary.
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
ACG::SceneGraph::TextureNode * textureNode()
Return pointer to the texture node.
void setIndexPropertyName(std::string _indexPropertyName)
set the name of the property used for texture index specification
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
QMenu * contextMenu_
Stores the per object context menu.
bool setImage(QString _textureName, int _id)
Stores the given image in the texture information.
Definition: TextureData.cc:221
void setTextureMap(std::map< int, GLuint > *_map)
Setup a mapping between internal texture ids on the mesh and the ids for the loaded textures in openg...
Definition: MeshNode2T.hh:493
void set_texture(const QImage &_image)
Uses a QImage to set the texture.
Definition: TextureNode.cc:309
void setHalfedgeTextcoordPropertyName(std::string _halfedgeTextcoordPropertyName)
Set the name of the per face texture coordinate property.
DrawMode SOLID_ENV_MAPPED
draw environment mapped
Definition: DrawModes.cc:93
PolyhedralMesh * polyhedralMesh(BaseObjectData *_object)
Get an PolyhedralMesh from an object.
QString name()
Return a name for the plugin.
bool addMultiTexture(QString _textureName)
Adds a new multiTexture ( This texture will only contain a list of enabled textures for multitexturin...
Definition: TextureData.cc:198
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:741
ACG::SceneGraph::DrawModes::DrawMode drawMode(int _viewer)
Get the current draw Mode of a Viewer.
#define VIEWMENU
The Menu will be added inside the View Menu.
GLuint add_texture(const QImage &_image)
Add a texture to this node.
Definition: TextureNode.cc:469
void slotTextureContextMenu(QAction *_action)
Called when the context menu has been triggered.
void disableTexture(QString _textureName)
Disable a given texture.
Definition: TextureData.cc:146
ACG::SceneGraph::MeshNodeT< MeshT > * meshNode()
Get the Scenegraph Mesh Node.
Definition: MeshObjectT.cc:630
PolyhedralMeshObject * polyhedralMeshObject(BaseObjectData *_object)
Cast an BaseObject to an PolyhedralMeshObject if possible.
void set_repeat(bool _status)
set texture repeat status
Definition: TextureNode.hh:119
DrawMode SOLID_TEXTURED_SHADED
draw smooth shaded textured faces
Definition: DrawModes.cc:95
TextureControlPlugin()
Constructor.
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
void handleFileOpenTextures(MeshT *&_mesh, int _objectId)
Handles data stored in new opened files ( e.g. Texture Information )
#define DATA_POLY_MESH
Definition: PolyMesh.hh:65
#define DATA_BSPLINE_SURFACE
ACG::SceneGraph::EnvMapNode * textureNode()
Get the TextureNode (actually its an environment map node) of the bspline surface.
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:66
HexahedralMesh * hexahedralMesh(BaseObjectData *_object)
Get an HexahedralMesh from an object.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
QStringList multiTextureList
If this is a multiTexture, the list will contain all textures for this multi Texture node...
Definition: TextureData.hh:152
bool textureExists(QString _textureName)
Check if a texture exists.
Definition: TextureData.cc:93
PerObjectData * objectData(QString _dataName)
Returns the object data pointer.
Definition: BaseObject.cc:814