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