DecimaterPlugin.cc 16 KB
Newer Older
1 2 3
/*===========================================================================*\
 *                                                                           *
 *                              OpenFlipper                                  *
Jan Möbius's avatar
Jan Möbius committed
4
 *      Copyright (C) 2001-2010 by Computer Graphics Group, RWTH Aachen      *
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 33 34 35 36
 *                           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/>.                                      *
 *                                                                           *
\*===========================================================================*/

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


Jan Möbius's avatar
 
Jan Möbius committed
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
//=============================================================================
//
//  CLASS DecimaterPlugin - IMPLEMENTATION
//
//=============================================================================


//== INCLUDES =================================================================

#include <QtGui>

#include "DecimaterPlugin.hh"

#include <iostream>
#include <ACG/GL/GLState.hh>
#include <QStringList>
#include <ACG/Scenegraph/ManipulatorNode.hh>

#include <OpenFlipper/BasePlugin/PluginFunctions.hh>

#define DECIMATER "DecimaterData"

//== IMPLEMENTATION ==========================================================

Jan Möbius's avatar
Jan Möbius committed
68
void DecimaterPlugin::initializePlugin()
Jan Möbius's avatar
 
Jan Möbius committed
69 70 71
{
  tool_ = new DecimaterToolbarWidget();
  QSize size(100, 100);
Jan Möbius's avatar
Jan Möbius committed
72 73
  tool_->resize(size);

Jan Möbius's avatar
 
Jan Möbius committed
74
  // connect signals->slots
Jan Möbius's avatar
Jan Möbius committed
75
  connect(tool_->pbDecimate,SIGNAL(clicked() ),this,SLOT(slot_decimate()));
Jan Möbius's avatar
Jan Möbius committed
76

Dirk Wilden's avatar
Dirk Wilden committed
77 78
  connect(tool_->roundness,SIGNAL(valueChanged(double) ),this,SLOT(updateRoundness(double)) );
  connect(tool_->roundnessSlider,SIGNAL(valueChanged(int) ),this,SLOT(updateRoundness(int)) );
79 80 81 82 83
  connect(tool_->distance,SIGNAL(valueChanged(double) ),this,SLOT(updateDistance()) );
  connect(tool_->normalDeviation,SIGNAL(valueChanged(int) ),this,SLOT(updateNormalDev()) );
  connect(tool_->normalDeviationSlider,SIGNAL(valueChanged(int) ),this,SLOT(updateNormalDev()) );
  connect(tool_->verticesCount,SIGNAL(valueChanged(int) ),this,SLOT(updateVertices()) );
  connect(tool_->verticesCountSlider,SIGNAL(valueChanged(int) ),this,SLOT(updateVertices()) );
Dirk Wilden's avatar
Dirk Wilden committed
84

85 86 87
  // Force update if the Toolbox gets visible
  connect(tool_, SIGNAL(showing()), this, SLOT( slotUpdateNumVertices() ) );

Jan Möbius's avatar
Jan Möbius committed
88
  emit addToolbox( tr("Decimater") , tool_ );
Dirk Wilden's avatar
Dirk Wilden committed
89 90
}

Dirk Wilden's avatar
Dirk Wilden committed
91 92 93 94 95
/** \brief Initialization of the plugin when it is loaded by the core
 * 
 */
void DecimaterPlugin::pluginsInitialized() {

96
  emit setSlotDescription("decimate(int,QVariantMap)",tr("Decimate a given object"),
Jan Möbius's avatar
Jan Möbius committed
97 98
                          QString(tr("objectId,constraints")).split(","),
                          QString(tr("ID of an object; Object that can has one or more constraint properties (distance,normal_deviation,roundness,vertices)")).split(";"));
Dirk Wilden's avatar
Dirk Wilden committed
99 100
}

Dirk Wilden's avatar
Dirk Wilden committed
101 102 103 104 105 106 107 108 109 110

//-----------------------------------------------------------------------------

/** \brief sync between values of roundness slider and spinbox in the toolbox
 *
 * @param _value new roundness value
 */
void DecimaterPlugin::updateRoundness(int _value)
{
  tool_->roundness->setValue( (double) _value / 100.0 );
111
  tool_->cbRoundness->setChecked (true);
Dirk Wilden's avatar
Dirk Wilden committed
112 113 114 115 116 117 118 119 120 121 122 123
}


//-----------------------------------------------------------------------------

/** \brief sync between values of roundness slider and spinbox in the toolbox
 *
 * @param _value new roundness value
 */
void DecimaterPlugin::updateRoundness(double _value)
{
  tool_->roundnessSlider->setValue( (int) (_value * 100) );
124
  tool_->cbRoundness->setChecked (true);
Jan Möbius's avatar
 
Jan Möbius committed
125 126 127 128
}

//-----------------------------------------------------------------------------

Dirk Wilden's avatar
Dirk Wilden committed
129 130 131 132
/** \brief Decimation called by toolbox
 *
 */
void DecimaterPlugin::slot_decimate()
Jan Möbius's avatar
 
Jan Möbius committed
133
{
134
  
Jan Möbius's avatar
Jan Möbius committed
135
  for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DATA_TRIANGLE_MESH) ;
Jan Möbius's avatar
 
Jan Möbius committed
136 137 138 139 140 141
                                        o_it != PluginFunctions::objectsEnd(); ++o_it)  {

    //initialize
    TriMeshObject* object = PluginFunctions::triMeshObject(*o_it);

    if ( object == 0 )
Jan Möbius's avatar
Jan Möbius committed
142
      emit log(LOGWARN , tr("Unable to get object"));
Jan Möbius's avatar
 
Jan Möbius committed
143 144

    DecimaterInfo* decimater = dynamic_cast< DecimaterInfo* > ( o_it->objectData(DECIMATER) );
Jan Möbius's avatar
Jan Möbius committed
145

146 147
    TriMesh* mesh = PluginFunctions::triMesh(*o_it);
  
Jan Möbius's avatar
 
Jan Möbius committed
148
    if (decimater == 0){
149
      decimater = new DecimaterInfo();
Jan Möbius's avatar
 
Jan Möbius committed
150 151
      o_it->setObjectData(DECIMATER, decimater);
    }
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
    
    // Constraint handles for decimation
    ModNormalFlippingH     hModNormalFlipping;
    ModQuadricH            hModDistance;
    ModRoundnessH          hModRoundness;
    ModQuadricH            hModPriorityQuadric;
    
    // Create decimater
    DecimaterType decimater_object( *mesh );
    decimater_object.add( hModPriorityQuadric );
    decimater_object.module( hModPriorityQuadric ).unset_max_err();
    
    // Remove old constraints
    if(decimater->distance()) {
        decimater->removeDistanceConstraint();
        decimater_object.remove(hModDistance);
    }
    if(decimater->normalDeviation()) {
        decimater->removeNormalDeviationConstraint();
        decimater_object.remove(hModNormalFlipping);
    }
    if(decimater->roundness()) {
        decimater->removeRoundnessConstraint();
        decimater_object.remove(hModRoundness);
    }
Jan Möbius's avatar
Jan Möbius committed
177

Dirk Wilden's avatar
Dirk Wilden committed
178
    //and set new constraints
179 180 181 182 183 184
    if ( tool_->cbDistance->isChecked() ) {
      if (  decimater_object.add( hModDistance ) ) {
          decimater->setDistanceConstraint( tool_->distance->value() );
          decimater_object.module( hModDistance ).set_max_err( decimater->distanceValue() );
      }
    }
Jan Möbius's avatar
Jan Möbius committed
185

186 187 188 189 190 191
    if ( tool_->cbNormalDev->isChecked() ) {
      if (  decimater_object.add( hModNormalFlipping ) ) {
          decimater->setNormalDeviationConstraint( tool_->normalDeviation->value() );
          decimater_object.module( hModNormalFlipping ).set_normal_deviation( decimater->normalDeviationValue() );
      }
    }
Dirk Wilden's avatar
Dirk Wilden committed
192

193 194 195 196 197 198
    if ( tool_->cbRoundness->isChecked() ) {      
      if (  decimater_object.add( hModRoundness ) ) {
          decimater->setRoundnessConstraint( tool_->roundness->value() );
          decimater_object.module( hModRoundness ).set_min_roundness( decimater->roundnessValue(), true );
      }
    }
Dirk Wilden's avatar
Dirk Wilden committed
199

200 201
    // Initialize the decimater
    if( ! decimater_object.initialize() ){
Jan Möbius's avatar
Jan Möbius committed
202
      emit log(LOGWARN, tr("Decimater could not be initialized"));
Jan Möbius's avatar
 
Jan Möbius committed
203 204 205 206
      continue;
    }

    //decimate
207
    if ( tool_->cbVertices->isChecked() )
208
        decimater_object.decimate_to(tool_->verticesCount->value());
Jan Möbius's avatar
 
Jan Möbius committed
209
    else
210
        decimater_object.decimate();
Jan Möbius's avatar
Jan Möbius committed
211

Jan Möbius's avatar
 
Jan Möbius committed
212 213 214
    object->mesh()->garbage_collection();
    object->mesh()->update_normals();
    object->update();
215
    
216 217
    // Create backup
    emit createBackup(o_it->id(), "Decimation");
218
    emit updatedObject( o_it->id() , UPDATE_TOPOLOGY );
Jan Möbius's avatar
 
Jan Möbius committed
219 220 221 222 223
  }

  emit updateView();
}

Dirk Wilden's avatar
 
Dirk Wilden committed
224 225 226

//-----------------------------------------------------------------------------

Dirk Wilden's avatar
Dirk Wilden committed
227 228 229 230 231 232
/** \brief Decimation called by Scripting
 *
 * @param _objID id of an object
 * @param _constraints A string containing a comma separated list of constraints (distance,normal_deviation,roundness,triangles)
 * @param _values a string containing a comma separated list of constraint values suited to the _constraints parameter
 */
233
void DecimaterPlugin::decimate(int _objID, QVariantMap _constraints) {
Dirk Wilden's avatar
 
Dirk Wilden committed
234

Jan Möbius's avatar
Jan Möbius committed
235

Dirk Wilden's avatar
 
Dirk Wilden committed
236 237
  BaseObjectData* baseObjectData;
  if ( ! PluginFunctions::getObject(_objID,baseObjectData) ) {
Jan Möbius's avatar
Jan Möbius committed
238
    emit log(LOGERR,tr("Unable to get Object"));
Dirk Wilden's avatar
 
Dirk Wilden committed
239 240 241 242 243 244 245
    return;
  }

  if ( baseObjectData->dataType() == DATA_TRIANGLE_MESH ) {
    TriMeshObject* object = PluginFunctions::triMeshObject(baseObjectData);

    if ( object == 0 ) {
Jan Möbius's avatar
Jan Möbius committed
246
      emit log(LOGWARN , tr("Unable to get object ( Only Triangle Meshes supported)"));
Dirk Wilden's avatar
 
Dirk Wilden committed
247 248 249 250
      return;
    }

    DecimaterInfo* decimater = dynamic_cast< DecimaterInfo* > ( object->objectData(DECIMATER) );
Jan Möbius's avatar
Jan Möbius committed
251

252 253
    TriMesh* mesh = PluginFunctions::triMesh(baseObjectData);
    
Dirk Wilden's avatar
 
Dirk Wilden committed
254
    if (decimater == 0){
255
      decimater = new DecimaterInfo();
Dirk Wilden's avatar
 
Dirk Wilden committed
256 257
      object->setObjectData(DECIMATER, decimater);
    }
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
    
    // Constraint handles for decimation
    ModNormalFlippingH     hModNormalFlipping;
    ModQuadricH            hModDistance;
    ModRoundnessH          hModRoundness;
    ModQuadricH            hModPriorityQuadric;
    
    // Create decimater
    DecimaterType decimater_object( *mesh );
    decimater_object.add( hModPriorityQuadric );
    decimater_object.module( hModPriorityQuadric ).unset_max_err();

    // Remove old constraints
    if(decimater->distance()) {
        decimater->removeDistanceConstraint();
        decimater_object.remove(hModDistance);
    }
    if(decimater->normalDeviation()) {
        decimater->removeNormalDeviationConstraint();
        decimater_object.remove(hModNormalFlipping);
    }
    if(decimater->roundness()) {
        decimater->removeRoundnessConstraint();
        decimater_object.remove(hModRoundness);
    }
Dirk Wilden's avatar
Dirk Wilden committed
283 284

    //distance constraint
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
285
    if ( _constraints.contains("distance") ){
Dirk Wilden's avatar
Dirk Wilden committed
286

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
287
      bool ok;
Dirk Wilden's avatar
Dirk Wilden committed
288

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
289
      double value = _constraints["distance"].toDouble(&ok);
Dirk Wilden's avatar
Dirk Wilden committed
290

291 292 293 294 295 296
      if (ok) {
        if (  decimater_object.add( hModDistance ) ) {
            decimater->setDistanceConstraint( value );
            decimater_object.module( hModDistance ).set_max_err( decimater->distanceValue() );
        }
      }
Dirk Wilden's avatar
Dirk Wilden committed
297
    }
Jan Möbius's avatar
Jan Möbius committed
298

Dirk Wilden's avatar
Dirk Wilden committed
299
    //normal deviation constraint
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
300
    if ( _constraints.contains("normal_deviation") ){
Dirk Wilden's avatar
Dirk Wilden committed
301

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
302
      bool ok;
Dirk Wilden's avatar
Dirk Wilden committed
303

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
304
      int value = _constraints["normal_deviation"].toInt(&ok);
Dirk Wilden's avatar
Dirk Wilden committed
305

306 307 308 309 310 311
      if (ok) {
        if (  decimater_object.add( hModNormalFlipping ) ) {
            decimater->setNormalDeviationConstraint( value );
            decimater_object.module( hModNormalFlipping ).set_normal_deviation( decimater->normalDeviationValue() );
        }
      }
Dirk Wilden's avatar
Dirk Wilden committed
312 313 314
    }

    //roundness constraint
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
315
    if ( _constraints.contains("roundness") ){
Dirk Wilden's avatar
Dirk Wilden committed
316

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
317
      bool ok;
Dirk Wilden's avatar
Dirk Wilden committed
318

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
319
      double value = _constraints["roundness"].toDouble(&ok);
Dirk Wilden's avatar
Dirk Wilden committed
320

321 322 323 324 325 326
      if (ok) {
        if (  decimater_object.add( hModRoundness ) ) {
            decimater->setRoundnessConstraint( value );
            decimater_object.module( hModRoundness ).set_min_roundness( decimater->roundnessValue(), true );
        }
      }
Dirk Wilden's avatar
Dirk Wilden committed
327 328 329 330 331 332
    }

    //triangleCount constraint
    bool triangleCount = false;
    int triangles = 0;

333
    if ( _constraints.contains("vertices") ){
Dirk Wilden's avatar
Dirk Wilden committed
334

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
335
      bool ok;
Dirk Wilden's avatar
Dirk Wilden committed
336

337
      int value = _constraints["vertices"].toInt(&ok);
Dirk Wilden's avatar
Dirk Wilden committed
338

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
339 340 341
      if (ok){
        triangleCount = true;
        triangles = value;
Dirk Wilden's avatar
Dirk Wilden committed
342 343 344 345
      }
    }

    //init the decimater
346
    if( ! decimater_object.initialize() ){
Jan Möbius's avatar
Jan Möbius committed
347
      emit log(LOGWARN, tr("Decimater could not be initialized"));
Jan Möbius's avatar
Jan Möbius committed
348
      return;
Dirk Wilden's avatar
 
Dirk Wilden committed
349 350 351
    }

    //decimate
Dirk Wilden's avatar
Dirk Wilden committed
352
    if ( triangleCount )
353
      decimater_object.decimate_to( triangles ); // do decimation
Dirk Wilden's avatar
 
Dirk Wilden committed
354
    else
355
      decimater_object.decimate(); // do decimation
Jan Möbius's avatar
Jan Möbius committed
356

Dirk Wilden's avatar
 
Dirk Wilden committed
357 358 359 360
    object->mesh()->garbage_collection();
    object->mesh()->update_normals();
    object->update();

361 362 363
    // Create backup
    emit createBackup(_objID, "Decimation");
    
364 365 366 367 368 369
    // Create QVariantMap parameter string
    QString param = "("  + (_constraints.contains("distance") ? tr("distance = %1").arg(_constraints["distance"].toString()) : "") +
                    ", " + (_constraints.contains("normal_deviation") ? tr("normal_deviation = %1").arg(_constraints["normal_deviation"].toString()) : "") +
                    ", " + (_constraints.contains("roundness") ? tr("roundness = %1").arg(_constraints["roundness"].toString()) : "") +
                    ", " + (_constraints.contains("vertices") ? tr("vertices = %1").arg(_constraints["vertices"].toString()) : "") + ")";
    
370 371 372
    emit scriptInfo( "decimate(" + QString::number(_objID) + ", " + param + ")" );
    
    emit updatedObject( baseObjectData->id() , UPDATE_TOPOLOGY);
373

Dirk Wilden's avatar
 
Dirk Wilden committed
374
  } else {
Jan Möbius's avatar
Jan Möbius committed
375
    emit log(LOGERR,tr("Unsupported object type for decimater"));
Dirk Wilden's avatar
 
Dirk Wilden committed
376 377 378
    return;
  }

379
  emit updateView();
Dirk Wilden's avatar
 
Dirk Wilden committed
380 381
}

Jan Möbius's avatar
 
Jan Möbius committed
382 383
//-----------------------------------------------------------------------------

384 385 386 387 388 389 390
void DecimaterPlugin::slotUpdateNumVertices()
{
  // Only update if tool is visible
  if ( !tool_->isVisible() ) {
    return;
  }

Jan Möbius's avatar
Jan Möbius committed
391
  int max = 0;
392 393 394 395 396 397 398 399 400 401 402 403 404 405
  int div = 0;

  bool ok;
  emit functionExists( "info" , "vertexCount(int)", ok  ) ;
  if (!ok)
  {
    tool_->currentNumVertices->setText ("<not available>");
    return;
  }

  for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS,DataType(DATA_TRIANGLE_MESH)) ;
                                        o_it != PluginFunctions::objectsEnd(); ++o_it)  {


Jan Möbius's avatar
Jan Möbius committed
406
    max = std::max( RPC::callFunctionValue<int>   ("info" , "vertexCount",o_it->id()) , max );
407 408 409 410 411
    div++;
  }

  if (div <= 0)
    tool_->currentNumVertices->setText ("<not available>");
Jan Möbius's avatar
Jan Möbius committed
412 413 414 415
  else {
    tool_->currentNumVertices->setText (QString::number(max));
    tool_->verticesCount->setMaximum(max);
    tool_->verticesCountSlider->setMaximum(max);
Dirk Wilden's avatar
Dirk Wilden committed
416 417 418
    
    if ( tool_->verticesCount->value() < 2 )
      tool_->verticesCount->setValue( max / 2 );
Jan Möbius's avatar
Jan Möbius committed
419
  }
420 421 422 423 424 425 426 427 428 429 430
}

//-----------------------------------------------------------------------------

void DecimaterPlugin::slotObjectSelectionChanged(int /*_identifier*/)
{
  slotUpdateNumVertices ();
}

//-----------------------------------------------------------------------------

431
void DecimaterPlugin::slotObjectUpdated(int /*_identifier*/ , const UpdateType _type )
432
{
433 434
  if ( _type.contains(UPDATE_TOPOLOGY) )
    slotUpdateNumVertices ();
435 436 437 438
}

//-----------------------------------------------------------------------------

439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
// activate checkbox if value has changed
void DecimaterPlugin::updateVertices()
{
  tool_->cbVertices->setChecked (true);
}

//-----------------------------------------------------------------------------

// activate checkbox if value has changed
void DecimaterPlugin::updateNormalDev()
{
  tool_->cbNormalDev->setChecked (true);
}

//-----------------------------------------------------------------------------

// activate checkbox if value has changed
void DecimaterPlugin::updateDistance()
{
  tool_->cbDistance->setChecked (true);
}

//-----------------------------------------------------------------------------

463
Q_EXPORT_PLUGIN2(DecimaterPlugin , DecimaterPlugin );
Jan Möbius's avatar
 
Jan Möbius committed
464