TextureControl.cc 73.2 KB
Newer Older
1
/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
2 3
*                                                                            *
*                              OpenFlipper                                   *
Jan Möbius's avatar
Jan Möbius committed
4
*      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen       *
Jan Möbius's avatar
Jan Möbius committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
*                           www.openflipper.org                              *
*                                                                            *
*--------------------------------------------------------------------------- *
*  This file is part of OpenFlipper.                                         *
*                                                                            *
*  OpenFlipper is free software: you can redistribute it and/or modify       *
*  it under the terms of the GNU Lesser General Public License as            *
*  published by the Free Software Foundation, either version 3 of            *
*  the License, or (at your option) any later version with the               *
*  following exceptions:                                                     *
*                                                                            *
*  If other files instantiate templates or use macros                        *
*  or inline functions from this file, or you compile this file and          *
*  link it with other files to produce an executable, this file does         *
*  not by itself cause the resulting executable to be covered by the         *
*  GNU Lesser General Public License. This exception does not however        *
*  invalidate any other reasons why the executable file might be             *
*  covered by the GNU Lesser General Public License.                         *
*                                                                            *
*  OpenFlipper is distributed in the hope that it will be useful,            *
*  but WITHOUT ANY WARRANTY; without even the implied warranty of            *
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
*  GNU Lesser General Public License for more details.                       *
*                                                                            *
*  You should have received a copy of the GNU LesserGeneral Public           *
*  License along with OpenFlipper. If not,                                   *
*  see <http://www.gnu.org/licenses/>.                                       *
*                                                                            *
33 34 35
\*===========================================================================*/

/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
36 37 38 39 40
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
41
\*===========================================================================*/
Jan Möbius's avatar
 
Jan Möbius committed
42 43 44 45




46

Jan Möbius's avatar
 
Jan Möbius committed
47 48 49 50 51
#include <QtGui>

#include "TextureControl.hh"

#include <iostream>
52
#include <ACG/GL/GLState.hh>
Jan Möbius's avatar
 
Jan Möbius committed
53 54

#include "OpenFlipper/BasePlugin/PluginFunctions.hh"
Jan Möbius's avatar
Jan Möbius committed
55
#include "OpenFlipper/BasePlugin/PluginFunctionsViewControls.hh"
Jan Möbius's avatar
 
Jan Möbius committed
56
#include "OpenFlipper/common/GlobalOptions.hh"
57
#include "ImageStorage.hh"
Jan Möbius's avatar
 
Jan Möbius committed
58

59 60
#include <math.h>

61
#define TEXTUREDATA "TextureData"
62
 
63

Dirk Wilden's avatar
Dirk Wilden committed
64 65 66 67 68
void TextureControlPlugin::slotTextureAdded( QString _textureName , QString _filename , uint _dimension , int _id)
{
  // Get the new object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
69
    emit log(LOGERR,"slotTextureAdded: Unable to get Object for id " + QString::number(_id) );
70
    return;
Dirk Wilden's avatar
Dirk Wilden committed
71 72 73 74 75 76 77 78 79
  }

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

80
  if ( texData->textureExists(_textureName) ) {
81
    emit log(LOGERR,"slotTextureAdded: Trying to add already existing texture " + _textureName + " for object " + QString::number(_id) );
Dirk Wilden's avatar
Dirk Wilden committed
82 83
    return;
  }
84 85 86 87 88

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

89 90
  // Add Image to the image store and set the index in the texture description
  int newId = imageStore().addImageFile(_filename);
Dirk Wilden's avatar
 
Dirk Wilden committed
91

92 93 94 95
  if ( newId == -1 ) {
    emit log(LOGERR,imageStore().error());
    return;
  }
96 97 98 99 100 101 102 103

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

  //inform textureNode about the new texture
  if( obj->dataType( DATA_TRIANGLE_MESH ) )
104
    glName = PluginFunctions::triMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newId,0));
105 106

  if ( obj->dataType( DATA_POLY_MESH ) )
107
    glName = PluginFunctions::polyMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newId,0));
108 109 110 111 112 113

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

  if (glName == 0) {
114
    emit log(LOGERR,"slotTextureAdded: Unable to bind texture!");
115 116 117 118
    return;
  }

  texData->addTexture(_textureName,_filename,_dimension,glName);
119 120 121 122

  // Remember id in texture descriptor
  texData->setImage(_textureName,newId);

123
  texData->texture(_textureName).disable();
Dirk Wilden's avatar
Dirk Wilden committed
124 125
}

Jan Möbius's avatar
 
Jan Möbius committed
126 127
void TextureControlPlugin::slotTextureAdded( QString _textureName , QString _filename , uint _dimension)
{
128 129 130
  // Add this texture to the list of global textures
  if ( ! globalTextures_.textureExists(_textureName) ) {
    globalTextures_.addTexture(_textureName,_filename,_dimension,0);
131
    globalTextures_.texture(_textureName).disable();
132

133
    int newImageId = imageStore().addImageFile(_filename);
Dirk Wilden's avatar
 
Dirk Wilden committed
134

135 136 137 138
    if ( newImageId == -1 ) {
      emit log(LOGERR,imageStore().error());
      return;
    }
Dirk Wilden's avatar
 
Dirk Wilden committed
139

140
    globalTextures_.texture(_textureName).textureImageId(newImageId);
141

142
  } else {
143
    emit log(LOGERR,"slotTextureAdded: Trying to add already existing global texture " + _textureName );
144 145
    return;
  }
146

147
  // Add a new entry to the global Texture menu
Jan Möbius's avatar
 
Jan Möbius committed
148
  QAction* new_texture = new QAction(_textureName, this);
149
  new_texture->setStatusTip(tr("slotTextureAdded: Switch all objects to this Texture ( if available )"));
Jan Möbius's avatar
 
Jan Möbius committed
150 151 152 153 154
  new_texture->setCheckable(true);
  actionGroup_->addAction(new_texture);
  textureMenu_->addAction(new_texture);
  new_texture->setChecked(true);
  textureActions_.push_back(new_texture);
155

156
}
157

158
void TextureControlPlugin::slotMultiTextureAdded( QString _textureGroup , QString _name , QString _filename , int _id , int& _textureId ) {
159 160 161
   // Get the new object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
162
    emit log(LOGERR,"slotMultiTextureAdded: Unable to get Object for id " + QString::number(_id) );
163 164 165 166
  }

  // Check if we support this kind of data
  if ( !obj->dataType(DATA_TRIANGLE_MESH) && !obj->dataType(DATA_POLY_MESH) ) {
167
      emit log(LOGERR,"slotMultiTextureAdded: Trying to add textures to object failed because of unsupported object type");
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
      return;
  }

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

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

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

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

188 189 190
  //hide the texture (its accessible through the multiTexture)
  texData->texture(_name).hidden( true );

191 192
  // Add to image store
  int newImageId = imageStore().addImageFile(_name);
Dirk Wilden's avatar
 
Dirk Wilden committed
193

194 195 196 197
  if ( newImageId == -1 ) {
    emit log(LOGERR,imageStore().error());
    return;
  }
Dirk Wilden's avatar
 
Dirk Wilden committed
198

199 200
  // Add to texture description
  texData->texture(_name).textureImageId(newImageId);
201 202 203 204 205

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

}

void TextureControlPlugin::addedEmptyObject( int _id ) {
212 213 214 215
  
  // Get the new object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
216
//     emit log(LOGERR,"addedEmptyObject: Unable to get Object for id " + QString::number(_id) );
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
    return;
  }
  
  // Check if we support this kind of data
  if ( !obj->dataType(DATA_TRIANGLE_MESH) && !obj->dataType(DATA_POLY_MESH) ) {
    return;
  }
  
  // Get Texture data for this object or create one if it does not exist
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0){
    texData = new TextureData();
    obj->setObjectData(TEXTUREDATA, texData);
  }
  
  // Iterate over all available global textures and add them to the object
  for ( uint i = 0 ; i < globalTextures_.textures().size() ; ++i) {
234 235 236 237 238 239 240 241 242

    // Add to image store
    int newImageId = imageStore().addImageFile(globalTextures_.textures()[i].filename());

    if ( newImageId == -1 ) {
      emit log(LOGERR,imageStore().error());
      continue;
    }

243 244 245 246 247 248 249
    // ================================================================================
    // Add the texture to the texture node and get the corresponding id
    // ================================================================================
    GLuint glName = 0;
    
    //inform textureNode about the new texture
    if( obj->dataType( DATA_TRIANGLE_MESH ) )
250
      glName = PluginFunctions::triMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newImageId,0));
251 252
    
    if ( obj->dataType( DATA_POLY_MESH ) )
253
      glName = PluginFunctions::polyMeshObject(obj)->textureNode()->add_texture(imageStore().getImage(newImageId,0));
254 255 256 257 258 259
    
    // ================================================================================
    // Store texture information in objects metadata
    // ================================================================================
    if (glName != 0) {
      texData->addTexture(globalTextures_.textures()[i], glName);
260 261 262

      // Add to texture description
      texData->setImage(globalTextures_.textures()[i].name(),newImageId);
263 264
    }
    else {
265
      imageStore().removeImage(newImageId);
266
      emit log(LOGERR,"addedEmptyObject: Unable to bind Texture");
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
      continue;
    }
    
    
    // ================================================================================
    // Update texture mapping in meshNode
    // ================================================================================
    if( obj->dataType( DATA_TRIANGLE_MESH ) ){
      PluginFunctions::triMeshObject(obj)->meshNode()->setTextureMap( 0 );
    }
    
    if ( obj->dataType( DATA_POLY_MESH ) ){
      PluginFunctions::polyMeshObject(obj)->meshNode()->setTextureMap( 0 );
    }
    
  }
Jan Möbius's avatar
 
Jan Möbius committed
283 284
}

285
template< typename MeshT >
Jan Möbius's avatar
Jan Möbius committed
286
void TextureControlPlugin::handleFileOpenTextures( MeshT*& _mesh , int _objectId ) {
287

288 289 290 291 292 293
  // Get the new object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _objectId , obj ) ) {
    return;
  }

294 295 296
  // ================================================================================
  // Create a backup of the original per Vertex texture Coordinates
  // ================================================================================
297
  
298 299 300 301 302 303 304 305 306 307 308 309 310
  if ( _mesh->has_vertex_texcoords2D() ){
  
    OpenMesh::VPropHandleT< typename MeshT::TexCoord2D > oldVertexCoords;
    if ( !_mesh->get_property_handle(oldVertexCoords,"Original Per Vertex Texture Coords") )
      _mesh->add_property(oldVertexCoords,"Original Per Vertex Texture Coords");
    
    for ( TriMesh::VertexIter v_it = _mesh->vertices_begin(); v_it != _mesh->vertices_end(); ++v_it)
      _mesh->property(oldVertexCoords, v_it ) =  _mesh->texcoord2D( v_it );

    slotTextureAdded("Original Per Vertex Texture Coords","unknown.png",2,_objectId);
    slotSetTextureMode("Original Per Vertex Texture Coords","type=vertexbased",_objectId);
  }
  
311 312 313
  // ================================================================================
  // Create a backup of the original per Face texture Coordinates
  // ================================================================================
314
  
315 316 317 318 319 320 321 322 323 324 325 326
  if ( _mesh->has_halfedge_texcoords2D() ){
    
    OpenMesh::HPropHandleT< typename MeshT::TexCoord2D > oldHalfedgeCoords;
    if ( !_mesh->get_property_handle(oldHalfedgeCoords,"Original Per Face Texture Coords") )
      _mesh->add_property(oldHalfedgeCoords,"Original Per Face Texture Coords");
    
    for ( TriMesh::HalfedgeIter he_it = _mesh->halfedges_begin(); he_it != _mesh->halfedges_end(); ++he_it)
      _mesh->property(oldHalfedgeCoords, he_it ) =  _mesh->texcoord2D( he_it );

    slotTextureAdded("Original Per Face Texture Coords","unknown.png",2,_objectId);
    slotSetTextureMode("Original Per Face Texture Coords","type=halfedgebased",_objectId);
  }
327

328 329
}

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

333 334 335
  // Get the new object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
336
    emit log(LOGERR,"fileOpened: Unable to get Object for id " + QString::number(_id) );
337
    return;
338 339 340 341 342
  }

  // Check if we support this kind of data
  if ( !obj->dataType(DATA_TRIANGLE_MESH) && !obj->dataType(DATA_POLY_MESH) ) {
      return;
343 344
  }

345 346 347
  // Get Texture data for this object or create one if it does not exist
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0){
348 349
    emit log(LOGERR,tr("fileOpened: Unable to get texture object data for id %1.").arg(_id) );
    return;
Jan Möbius's avatar
 
Jan Möbius committed
350
  }
351 352 353 354 355

  // Check if the file contains a texture map, store original textures and handle them before adding global textures
  if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
    TriMesh* mesh = PluginFunctions::triMesh(obj);
    if ( mesh )
Jan Möbius's avatar
Jan Möbius committed
356
      handleFileOpenTextures(mesh,_id);
357 358 359
  } else if ( obj->dataType( DATA_POLY_MESH ) ) {
    PolyMesh* mesh = PluginFunctions::polyMesh(obj);
    if ( mesh )
Jan Möbius's avatar
Jan Möbius committed
360
      handleFileOpenTextures(mesh,_id);
361 362
  }

363 364
}

365 366 367 368 369 370 371
void TextureControlPlugin::slotTextureChangeImage( QString _textureName , QImage& _image , int _id ) {

  // ================================================================================
  // Get the new object
  // ================================================================================
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
372
    emit log(LOGERR,"slotTextureChangeImage: Unable to get Object for id " + QString::number(_id) );
373 374 375 376 377 378 379 380
  }

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

  if ( texData == 0 || ( !texData->textureExists(_textureName))  ) {
381
    emit log(LOGERR,"slotTextureChangeImage: Texture does not exist: " + _textureName + " (objectid=" + QString::number(_id) + ")");
382 383 384 385 386 387 388
    return;
  }

  // ================================================================================
  // Update the image
  // ================================================================================
  Texture& texture = texData->texture(_textureName);
389 390 391 392 393 394

  // Add to image store
  int newImageId = imageStore().addImage(_image);

  // Add to texture description
  texture.textureImageId(newImageId);
395 396 397 398 399

  // ================================================================================
  // Flag dirty or update
  // ================================================================================

400 401 402 403 404 405 406
  if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
    PluginFunctions::triMeshObject(obj)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
  } else if ( obj->dataType( DATA_POLY_MESH ) ) {
    PluginFunctions::triMeshObject(obj)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
  }

  emit updateView();
407 408 409 410 411 412 413 414 415

}

void TextureControlPlugin::slotTextureChangeImage( QString _textureName , QImage& _image ) {

  // ================================================================================
  // Update texture Image for global textures
  // ================================================================================
  if ( ! globalTextures_.textureExists(_textureName) ) {
416
    emit log(LOGERR,"slotTextureChangeImage: Global texture does not exist: " + _textureName);
417 418 419 420 421 422 423
    return;
  }

  // ================================================================================
  // Update the image in the global texture
  // ================================================================================
  Texture& texture = globalTextures_.texture(_textureName);
424 425 426 427 428 429

  // Add to image store
  int newImageId = imageStore().addImage(_image);

  // Add to texture description
  texture.textureImageId(newImageId);
430 431 432 433 434 435 436 437 438 439

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

    TextureData* texData = dynamic_cast< TextureData* > ( o_it->objectData(TEXTUREDATA) );
    if (texData != 0)
      if ( texData->textureExists(_textureName) ){
        Texture& localTex = texData->texture(_textureName);
440
        localTex.textureImageId(newImageId);
441

442 443 444 445 446
          if( o_it->dataType( DATA_TRIANGLE_MESH ) ) {
            PluginFunctions::triMeshObject(o_it)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
          } else if ( o_it->dataType( DATA_POLY_MESH ) ) {
            PluginFunctions::triMeshObject(o_it)->textureNode()->set_texture( _image , texData->texture(_textureName).glName());
          }
447 448 449
      }
  }

450 451
  emit updateView();

452 453
}

454 455 456 457 458
void TextureControlPlugin::slotTextureGetImage( QString _textureName, QImage& _image, int _id ){
  
  // Get the object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
459
    emit log(LOGERR,"slotTextureGetImage: Unable to get Object for id " + QString::number(_id) );
460 461 462 463 464 465 466
  }

  // ================================================================================
  // Get Texture data for current object
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0) {
467
    emit log(LOGERR, tr("slotTextureGetImage: Object has no texture data! Object: %1").arg(_id) );
468 469 470 471 472 473 474
    return;
  }

  // ================================================================================
  // Check for requested Texture
  // ================================================================================
  if ( !texData->textureExists(_textureName) ) {
475
    emit log(LOGERR, "slotTextureGetImage: Texture not available! " + _textureName );
476 477 478 479 480 481
    return;
  }

  if ( texData->texture(_textureName).type() == MULTITEXTURE )
    _image = QImage();
  else
482
    _image = imageStore().getImage(texData->texture(_textureName).textureImageId(),0 );
483 484
}

485

486 487 488
void TextureControlPlugin::slotTextureGetImage( QString _textureName, QImage& _image ){
  
  if ( ! globalTextures_.textureExists(_textureName) ) {
489
    emit log(LOGERR,"slotTextureGetImage: Global texture does not exist: " + _textureName);
490 491 492 493 494 495
    return;
  }

  if ( globalTextures_.texture(_textureName).type() == MULTITEXTURE )
    _image = QImage();
  else
496
    _image = imageStore().getImage(globalTextures_.texture(_textureName).textureImageId(),0);
497 498
}

499 500 501 502 503
void TextureControlPlugin::slotTextureIndex( QString _textureName, int _id, int& _index){
  
  // Get the object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
504
    emit log(LOGERR,"slotTextureIndex: Unable to get Object for id " + QString::number(_id) );
505 506 507 508 509 510 511
  }

  // ================================================================================
  // Get Texture data for current object
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0) {
512
    emit log(LOGERR, tr("slotTextureIndex: Object has no texture data! Object: %1").arg(_id) );
513 514 515 516 517 518 519
    return;
  }

  // ================================================================================
  // Check for requested Texture
  // ================================================================================
  if ( !texData->textureExists(_textureName) ) {
520
    emit log(LOGERR, "slotTextureIndex: Texture not available! " + _textureName );
521 522 523 524 525 526
    return;
  }

  _index = texData->texture(_textureName).id();
}

527 528 529 530 531
void TextureControlPlugin::slotTextureIndexPropertyName(int _id, QString& _propertyName) {
    
    // Get the object
    BaseObjectData* obj;
    if (! PluginFunctions::getObject(  _id , obj ) ) {
532
        emit log(LOGERR,"slotTextureIndexPropertyName: Unable to get Object for id " + QString::number(_id) );
533 534 535 536 537 538 539 540 541
        return;
    }
    
    // Get texture index property name
    if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
        _propertyName = PluginFunctions::triMeshObject(obj)->meshNode()->indexPropertyName().c_str();
    } else if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
        _propertyName = PluginFunctions::polyMeshObject(obj)->meshNode()->indexPropertyName().c_str();
    } else {
542
        emit log(LOGERR,"slotTextureIndexPropertyName: Unable to access mesh for object with id " + QString::number(_id) );
543 544 545
    }
}

546 547 548 549 550
void TextureControlPlugin::slotTextureName( int _id, int _textureIndex, QString& _textureName){
  
  // Get the object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
551
    emit log(LOGERR,"slotTextureName: Unable to get Object for id " + QString::number(_id) );
552 553 554 555 556 557 558
  }

  // ================================================================================
  // Get Texture data for current object
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0) {
559
    emit log(LOGERR, tr("slotTextureName: Object has no texture data! Object: %1").arg(_id) );
560 561 562 563 564 565 566 567 568
    return;
  }

  for (uint i=0; i < texData->textures().size(); i++ )
    if ( (texData->textures()[i]).id() == _textureIndex ){
      _textureName = (texData->textures()[i]).name();
      return;
    }

569
  emit log(LOGERR, "slotTextureName: TextureIndex not available! (" + QString::number(_textureIndex) + ")" );
570 571 572 573
  _textureName = "NOT_FOUND";
  return;
}

574 575 576 577 578
void TextureControlPlugin::slotTextureFilename( int _id, QString _textureName, QString& _textureFilename){
  
  // Get the object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
579
    emit log(LOGERR,"slotTextureFilename: Unable to get Object for id " + QString::number(_id) );
580 581 582 583 584 585 586
  }

  // ================================================================================
  // Get Texture data for current object
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0) {
587
    emit log(LOGERR, tr("slotTextureFilename: Object has no texture data! Object: %1").arg(_id) );
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
    return;
  }

  // Search in local textures
  for (uint i=0; i < texData->textures().size(); i++ ) {
      for (int j=0; j < texData->textures()[i].multiTextureList.size(); j++ ) {
          if ( (texData->textures()[i]).name() == _textureName ){
              Texture& tex = texData->texture((texData->textures()[i]).name());
              _textureFilename = tex.filename();
              return;
          } else if ( (texData->textures()[i]).multiTextureList[j] == _textureName ){
              Texture& tex = texData->texture((texData->textures()[i]).multiTextureList[j]);
              _textureFilename = tex.filename();
              return;
          }
      }
  }
  
  _textureFilename = OpenFlipper::Options::textureDir().path() + 
      QDir::separator().toAscii() + (globalTextures_.texture(_textureName)).filename();
  
  QFile f(_textureFilename);
  if(!f.exists()) _textureFilename = "NOT_FOUND";
  
  return;
}

615 616
void TextureControlPlugin::slotGetCurrentTexture( int _id, QString& _textureName ){
  
Dirk Wilden's avatar
Dirk Wilden committed
617 618
  _textureName = "NONE";
  
619 620 621
  // Get the object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
622
    emit log(LOGERR,"slotGetCurrentTexture: Unable to get Object for id " + QString::number(_id) );
623 624 625 626 627 628
  }

  // ================================================================================
  // Get Texture data for current object
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
629 630 631 632 633 634
  if (texData == 0) {
    #ifndef NDEBUG
    
      // Iterate over all per Object datas and output them
      QMap<QString, PerObjectData*>::const_iterator mapIter = obj->getPerObjectDataMap().begin();  
      while ( mapIter != obj->getPerObjectDataMap().end() ) {
635
        ++mapIter;
636 637 638
      }
    #endif
    
639
    return;
640
  }
641 642
  
  // Iterate over all available textures
643 644
  for ( uint i = 0 ; i < texData->textures().size() ; ++i) {
  
645 646 647
    if ( (texData->textures()[i]).enabled() ){
      _textureName = (texData->textures()[i]).name();
      
648
      if ( (texData->textures()[i]).type() == MULTITEXTURE ) {
649
        return;
650
      }
651
    }
652
  }
653 654 655 656 657 658
}

void TextureControlPlugin::slotGetSubTextures( int _id, QString _multiTextureName, QStringList& _subTextures ){
  // Get the object
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _id , obj ) ) {
659
    emit log(LOGERR,"slotGetSubTextures: Unable to get Object for id " + QString::number(_id) );
660 661 662 663 664 665 666
  }

  // ================================================================================
  // Get Texture data for current object
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0) {
667
    emit log(LOGERR, tr("slotGetSubTextures: Object has no texture data! Object: %1").arg(_id) );
668 669 670 671 672 673 674
    return;
  }

  // ================================================================================
  // Check for requested Texture
  // ================================================================================
  if ( !texData->textureExists(_multiTextureName) ) {
675
    emit log(LOGERR, "slotGetSubTextures: Texture not available! " + _multiTextureName );
676 677 678 679 680 681 682 683 684 685
    return;
  }
  
  if ( texData->texture(_multiTextureName).type() == MULTITEXTURE )
    _subTextures = texData->texture(_multiTextureName).multiTextureList;
  else
    _subTextures = QStringList();
}

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

687 688 689 690 691
  // ================================================================================
  // Get updated object
  // ================================================================================
  BaseObjectData* obj;
  if (! PluginFunctions::getObject(  _identifier , obj ) ) {
692
    emit log(LOGERR,"slotTextureUpdated: Unable to get Object for id " + QString::number(_identifier) );
Jan Möbius's avatar
 
Jan Möbius committed
693 694
    return;
  }
695

696 697 698 699
  //skip object if its not a mesh
  if( !obj->dataType( DATA_TRIANGLE_MESH ) && !obj->dataType( DATA_POLY_MESH ) )
    return;

700 701 702 703 704
  // ================================================================================
  // Get objects texture data and verify that texture exists
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0){
705
    emit log(LOGERR,tr("slotTextureUpdated: Texture data not found: Object %1" ).arg(_identifier) );
Jan Möbius's avatar
 
Jan Möbius committed
706
    return;
707
  }
Jan Möbius's avatar
 
Jan Möbius committed
708

709 710 711
  // ================================================================================
  // Check if texture exists
  // ================================================================================
712
  if ( ! texData->textureExists(_textureName) ) {
713
    emit log(LOGERR,"slotTextureUpdated: Texture " + _textureName + " not found on object " + QString::number(_identifier) );
714
    return;
715
  }
Jan Möbius's avatar
 
Jan Möbius committed
716

717 718 719
  // ================================================================================
  // If texture is not enabled, mark it as dirty and defer update to visualization update
  // ================================================================================
720
  if ( ! texData->texture(_textureName).enabled() ) {
721
    texData->texture(_textureName).setDirty();
722 723
    return;
  }
Jan Möbius's avatar
 
Jan Möbius committed
724

725
  // ================================================================================
726
  // Enable the texture in texture node
727 728 729 730
  // ================================================================================
  if( obj->dataType( DATA_TRIANGLE_MESH ) ) {
    TriMesh* mesh = PluginFunctions::triMesh(obj);
    doUpdateTexture(texData->texture(_textureName), *mesh);
731 732 733
    // Texture has been bound to that object by slotAddTexture.. directly or by fileOpened from global texture
    // Just activate it
    PluginFunctions::triMeshObject(obj)->textureNode()->activateTexture(texData->texture(_textureName).glName() );
734 735 736 737
    PluginFunctions::triMeshObject(obj)->textureNode()->set_repeat(texData->texture(_textureName).parameters.repeat);
  } else if ( obj->dataType( DATA_POLY_MESH ) ) {
    PolyMesh* mesh = PluginFunctions::polyMesh(obj);
    doUpdateTexture(texData->texture(_textureName), *mesh);
738 739 740
    // Texture has been bound to that object by slotAddTexture.. directly or by fileOpened from global texture
    // Just activate it
    PluginFunctions::polyMeshObject(obj)->textureNode()->activateTexture(texData->texture(_textureName).glName() );
741
    PluginFunctions::polyMeshObject(obj)->textureNode()->set_repeat(texData->texture(_textureName).parameters.repeat);
742
  }
Jan Möbius's avatar
 
Jan Möbius committed
743

744 745 746
  // ================================================================================
  // Mark texture as not dirty
  // ================================================================================
747
  texData->texture(_textureName).clean();
Jan Möbius's avatar
 
Jan Möbius committed
748

749 750 751 752 753
  // ================================================================================
  // Tell plugins to update texture
  // ================================================================================
  emit updatedObject(obj->id(),UPDATE_TEXTURE);

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

756 757 758 759 760 761
void TextureControlPlugin::slotUpdateTexture( QString _textureName , int _identifier) {
  if ( _textureName == "Reflection Lines" )
    slotTextureUpdated( _textureName , _identifier );

}

Jan Möbius's avatar
 
Jan Möbius committed
762
template< typename MeshT >
763
void TextureControlPlugin::doUpdateTexture ( Texture& _texture, MeshT& _mesh )
Jan Möbius's avatar
 
Jan Möbius committed
764
{
765

766
  if ( _texture.type() == HALFEDGEBASED ) {
767
    if (_texture.dimension() == 1) {
Jan Möbius's avatar
 
Jan Möbius committed
768 769

      OpenMesh::HPropHandleT< double > texture;
770
      if ( ! _mesh.get_property_handle(texture, _texture.name().toStdString() ) ) {
771
        emit log(LOGERR,tr("doUpdateTexture: HALFEDGEBASED dimension 1: Unable to get property %1").arg(_texture.name()) );
Jan Möbius's avatar
 
Jan Möbius committed
772 773 774
        return;
      }

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

777
    } else if ( _texture.dimension() == 2 ) {
Jan Möbius's avatar
 
Jan Möbius committed
778 779

      OpenMesh::HPropHandleT< OpenMesh::Vec2d > texture2D;
780
      if ( ! _mesh.get_property_handle( texture2D, _texture.name().toStdString() ) ) {
781
        emit log(LOGERR,tr("doUpdateTexture: HALFEDGEBASED dimension 2: Unable to get property %1").arg(_texture.name()) );
Jan Möbius's avatar
 
Jan Möbius committed
782 783 784
        return;
      }

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

787
    } else
788
      emit log(LOGERR, "doUpdateTexture: Unsupported Texture Dimension " + QString::number(_texture.dimension() ) );
789
  } else if ( _texture.type() == VERTEXBASED ) {
790
    if ( _texture.dimension() == 1 ) {
Jan Möbius's avatar
 
Jan Möbius committed
791 792

      OpenMesh::VPropHandleT< double > texture;
793
      if ( ! _mesh.get_property_handle(texture,_texture.name().toStdString() ) ) {
794
        emit log(LOGERR,tr("doUpdateTexture: VERTEXBASED dimension 1: Unable to get property %1").arg(_texture.name()) );
795
        return;
Jan Möbius's avatar
 
Jan Möbius committed
796 797
      }

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

800
      } else if ( _texture.dimension() == 2 ) {
Jan Möbius's avatar
 
Jan Möbius committed
801 802

        OpenMesh::VPropHandleT< OpenMesh::Vec2d >  texture2D;
803
        if ( ! _mesh.get_property_handle(texture2D,_texture.name().toStdString() ) ) {
804
          emit log(LOGERR,tr("doUpdateTexture: VERTEXBASED dimension 2: Unable to get property %1").arg(_texture.name()) );
805
          return;
Jan Möbius's avatar
 
Jan Möbius committed
806 807
        }

808
        copyTexture( _texture, _mesh, texture2D);
Jan Möbius's avatar
 
Jan Möbius committed
809 810

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

Jan Möbius's avatar
 
Jan Möbius committed
812
        OpenMesh::VPropHandleT< OpenMesh::Vec3d >  scalarField3D;
813 814
        if ( ! _mesh.get_property_handle(scalarField3D,_texture.name) ) {
          emit log(LOGERR,"Unable to get property " + _texture.name );
815
          return;
Jan Möbius's avatar
 
Jan Möbius committed
816
        }
817

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

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

Jan Möbius's avatar
 
Jan Möbius committed
823
    } else
824
      emit log(LOGERR, "doUpdateTexture: Unsupported Texture type");
825

Jan Möbius's avatar
 
Jan Möbius committed
826 827
}

828 829 830 831
void TextureControlPlugin::computeValue(Texture& _texture, double _min, double _max, double& _value) {
   const bool clamp         = _texture.parameters.clamp ;
   const bool center        = _texture.parameters.center;
   const double max_val     = _texture.parameters.max_val;
832
   const double min_val     = _texture.parameters.min_val;
833 834 835 836 837 838
   const bool abs           = _texture.parameters.abs;
   const double clamp_max   = _texture.parameters.clamp_max;
   const double clamp_min   = _texture.parameters.clamp_min;
   const bool scale         = _texture.parameters.scale;
   const double scaleFactor = fabs(_max) + fabs(_min);
   const bool repeat        = _texture.parameters.repeat;
839

Jan Möbius's avatar
 
Jan Möbius committed
840 841 842
   // Use absolute value as requested by plugin
   if ( abs )
      _value = fabs(_value);
843

Jan Möbius's avatar
 
Jan Möbius committed
844 845 846 847 848 849 850
   // Clamp if requested
   if ( clamp ) {
      if ( _value > clamp_max )
         _value = clamp_max;
      if (_value < clamp_min)
         _value = clamp_min;
   }
851

Dirk Wilden's avatar
Dirk Wilden committed
852 853 854 855 856 857 858 859 860 861 862
   // if all texCoords have the same value
   if ( _min == _max ){

      if ( ! repeat )
        _value = 0.0;
      else
        _value = max_val;

     return;
   }

Jan Möbius's avatar
 
Jan Möbius committed
863 864 865
   // if the texture should not be repeated, scale to 0..1
   if ( ! repeat ) {
      if (! center ) {
866
        if ( scale) {
Dirk Wilden's avatar
Dirk Wilden committed
867
          _value /= scaleFactor; //scaleFactor is != 0.0 (otherwise _min==_max)
868
          _value -= _min/scaleFactor;
Jan Möbius's avatar
 
Jan Möbius committed
869 870 871 872
        }
      } else {
         // the values above zero are mapped to 0.5..1 the negative ones to 0.5..0
         if (_value > 0.0) {
Dirk Wilden's avatar
Dirk Wilden committed
873
            _value /= ( _max * 2.0); //_max >= _value > 0.0
Jan Möbius's avatar
 
Jan Möbius committed
874 875
            _value += 0.5;
         } else {
Dirk Wilden's avatar
Dirk Wilden committed
876 877 878 879 880 881
            if ( _min == 0.0 ){
              _value = 0.0;
            } else {
              _value /= ( _min * 2.0);
              _value = 0.5 - _value;
            }
Jan Möbius's avatar
 
Jan Möbius committed
882 883 884 885
         }
      }
   } else {
      _value -= _min;
886 887
      _value *= (max_val - min_val) / (_max - _min);
      _value += min_val;
Jan Möbius's avatar
 
Jan Möbius committed
888
   }
889 890 891 892 893 894 895 896 897
   
   
}

void TextureControlPlugin::slotDrawModeChanged(int _viewerId ) {

  // Only update if we have a relevant draw mode
  if (! ( ( PluginFunctions::drawMode(_viewerId) == ACG::SceneGraph::DrawModes::SOLID_TEXTURED ) ||
          ( PluginFunctions::drawMode(_viewerId) == ACG::SceneGraph::DrawModes::SOLID_TEXTURED_SHADED) || 
Jan Möbius's avatar
Jan Möbius committed
898 899
          ( PluginFunctions::drawMode(_viewerId) == ACG::SceneGraph::DrawModes::SOLID_2DTEXTURED_FACE) ||
          ( PluginFunctions::drawMode(_viewerId) == ACG::SceneGraph::DrawModes::SOLID_2DTEXTURED_FACE_SHADED) )) {
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925
    return;
  }

  // Iterate over all Objects
  for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS) ;
                                         o_it != PluginFunctions::objectsEnd();
                                         ++o_it) {

    // Get the corresponding texture data
    TextureData* texData = dynamic_cast< TextureData* > ( o_it->objectData(TEXTUREDATA) );
    if (texData == 0){
      continue;
    }

    // Go over all textures and if one of them is enabled and dirty, update it here
    for ( uint i = 0; i < texData->textures().size(); ++i ) {
      if ( texData->textures()[i].enabled() && texData->textures()[i].dirty() ) {
        emit updateTexture( texData->textures()[i].name() , o_it->id() );
      }
    }


  }
  
  emit updateView();

Jan Möbius's avatar
 
Jan Möbius committed
926 927
}

928
void TextureControlPlugin::slotObjectUpdated(int _identifier, const UpdateType _type)
929 930 931 932
{  
    if( !_type.contains(UPDATE_ALL) && !_type.contains(UPDATE_GEOMETRY) && !_type.contains(UPDATE_TOPOLOGY) )
        return;
    
933 934 935 936 937
  // ================================================================================
  // Get updated object
  // ================================================================================
  if ( _identifier == -1 )
    return;
938

939
  BaseObjectData* obj;
940
  if (! PluginFunctions::getObject(  _identifier , obj ) )
941 942
    return;

943 944 945 946
  //skip object if its not a mesh
  if( !obj->dataType( DATA_TRIANGLE_MESH ) && !obj->dataType( DATA_POLY_MESH ) )
    return;

947 948 949 950 951 952 953 954 955 956 957 958 959
  // ================================================================================
  // Get objects texture data and verify that texture exists
  // ================================================================================
  TextureData* texData = dynamic_cast< TextureData* > ( obj->objectData(TEXTUREDATA) );
  if (texData == 0){
    return;
  }

  // ================================================================================
  // Set all textures to dirty
  // ================================================================================
  // TODO : if not in the texture rendering mode, do not emit update
  // Involves adding a interface part to react on draw mode changes
960
  // basic check implemented
961
  for ( uint i = 0; i < texData->textures().size(); ++i ) {
962
    texData->textures()[i].setDirty();
963 964 965 966 967

    bool update = false;
    for ( int j = 0 ; j < PluginFunctions::viewers() ; ++j ) {
       update |= ( PluginFunctions::drawMode(j) == ACG::SceneGraph::DrawModes::SOLID_TEXTURED );
       update |= ( PluginFunctions::drawMode(j) == ACG::SceneGraph::DrawModes::SOLID_TEXTURED_SHADED );
Jan Möbius's avatar
Jan Möbius committed
968 969
       update |= ( PluginFunctions::drawMode(j) == ACG::SceneGraph::DrawModes::SOLID_2DTEXTURED_FACE );
       update |= ( PluginFunctions::drawMode(j) == ACG::SceneGraph::DrawModes::SOLID_2DTEXTURED_FACE_SHADED );
970 971
    }

972
    if ( update && texData->textures()[i].enabled() )
973
      emit updateTexture( texData->textures()[i].name() , _identifier );
974
  }
975

Jan Möbius's avatar
 
Jan Möbius committed
976 977 978
}

void TextureControlPlugin::slotUpdateAllTextures( ) {
979 980 981 982 983 984
  std::cerr << "slotUpdateAllTextures: not implemented yet ... might be removed" << std::endl;
  // TODO : Check
//    // Force an update of all textures which are available for the updated object
//    for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS) ; o_it != PluginFunctions::objectsEnd(); ++o_it)
//       for ( uint i = 0 ; i < textures_.size() ; ++i )
//          emit updateTexture( textures_[i].name , o_it->id() );
Jan Möbius's avatar
 
Jan Möbius committed
985 986
}

987
bool TextureControlPlugin::parseMode( QString _mode, Texture& _texture ) {
988

989
  bool changed = false;
990

991 992 993 994 995 996
  int i = 0;
  QString nextString = _mode.section(',',i,i);
  while ( nextString != "" ) {
    QString sectionName = nextString.section('=',0,0);
    QString value = nextString.section('=',1,1);

997 998 999
    // Cleanup representation
    value       = value.trimmed();
    sectionName = sectionName.trimmed();
Jan Möbius's avatar
Jan Möbius committed
1000
    sectionName = sectionName.toLower();
1001

1002
    if ( sectionName == "clamp" ) {
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
      if ( StringToBool(value) != _texture.parameters.clamp ) {
        _texture.parameters.clamp = StringToBool(value);
        changed = true;
      }
    } else if ( sectionName == "clamp_max" ) {
      if (value.toDouble() != _texture.parameters.clamp_max){
        _texture.parameters.clamp_max = value.toDouble();
        changed = true;
      }
    } else if ( sectionName == "clamp_min" ) {
      if (value.toDouble() != _texture.parameters.clamp_min){
        _texture.parameters.clamp_min = value.toDouble();
        changed = true;
      }
    } else if ( sectionName == "max_val" ) {
      if (value.toDouble() != _texture.parameters.max_val){
        _texture.parameters.max_val = value.toDouble();
        changed = true;
      }
1022 1023 1024 1025 1026
    } else if ( sectionName == "min_val" ) {
      if (value.toDouble() != _texture.parameters.min_val){
        _texture.parameters.min_val = value.toDouble();
        changed = true;
      }
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
    } else if ( sectionName == "repeat" ) {
      if ( StringToBool(value) != _texture.parameters.repeat ) {
        _texture.parameters.repeat = StringToBool(value);
        changed = true;
      }
    } else if ( sectionName == "center" ) {
      if ( StringToBool(value) != _texture.parameters.center ) {
        _texture.parameters.center = StringToBool(value);
        changed = true;
      }
    } else if ( sectionName == "scale" ) {
      if ( StringToBool(value) != _texture.parameters.scale ) {
        _texture.parameters.scale = StringToBool(value);
        changed = true;
      }
1042 1043 1044 1045 1046 1047
    } else if ( sectionName == "abs" ) {
      if ( StringToBool(value) != _texture.parameters.abs ) {
        _texture.parameters.abs = StringToBool(value);
        changed = true;
      }
    } else if ( sectionName == "indexproperty" ) {
1048 1049 1050 1051
      if ( value != _texture.indexMappingProperty() ) {
        _texture.indexMappingProperty( value );
        changed = true;
      }
1052
    } else if ( sectionName == "visiblename" ) {
1053 1054 1055 1056
      if ( value != _texture.visibleName() ) {
        _texture.visibleName( value );
        changed = true;
      }
1057 1058 1059 1060 1061 1062 1063
    } else if ( sectionName == "type" ) {
        if ( ( value == "halfedgebased" ) && ( _texture.type() != HALFEDGEBASED ) ) {
          _texture.type( HALFEDGEBASED );
          changed = true;
        } else if ( (value == "vertexbased") && (_texture.type() != HALFEDGEBASED)  ) {
          _texture.type( VERTEXBASED );
          changed = true;
Jan Möbius's avatar
Jan Möbius committed
1064 1065 1066
        }  else if ( (value == "environmentmap") && (_texture.type() != ENVIRONMENT)  ) {
          _texture.type( ENVIRONMENT );
          changed = true;
1067
        } else {
1068
          emit log(LOGERR,"parseMode: Unknown texture type : " + value + " for texture: " + _texture.name() );
1069 1070
        }
    } else
1071
      emit log(LOGERR,"parseMode: Unknown texture mode : " + sectionName);
1072