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