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