1 /****************************************************************************
2 * MeshLab o o *
3 * A versatile mesh processing toolbox o o *
4 * _ O _ *
5 * Copyright(C) 2005 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23
24
25 #include <QString>
26 #include <QtGlobal>
27 #include <QFileInfo>
28 #include "meshmodel.h"
29 #include <wrap/gl/math.h>
30 #include "scriptinterface.h"
31 #include "mlexception.h"
32 #include "ml_shared_data_context.h"
33
34 #include <utility>
35
36 using namespace vcg;
37
38
39 //deletes each meshModel
~MeshDocument()40 MeshDocument::~MeshDocument()
41 {
42 foreach(MeshModel *mmp, meshList)
43 delete mmp;
44 foreach(RasterModel* rmp,rasterList)
45 delete rmp;
46 delete filterHistory;
47 }
48
49 //returns the mesh ata given position in the list
getMesh(int i)50 MeshModel *MeshDocument::getMesh(int i)
51 {
52 foreach(MeshModel *mmp, meshList)
53 {
54 if(mmp->id() == i) return mmp;
55 }
56 //assert(0);
57 return 0;
58 }
59
getMesh(const QString & name)60 MeshModel *MeshDocument::getMesh(const QString& name)
61 {
62 foreach(MeshModel *mmp, meshList)
63 {
64 if(mmp->shortName() == name) return mmp;
65 }
66 //assert(0);
67 return 0;
68 }
69
getMeshByFullName(const QString & pathName)70 MeshModel *MeshDocument::getMeshByFullName(const QString& pathName)
71 {
72 foreach(MeshModel *mmp, meshList)
73 {
74 if(mmp->fullName() == pathName) return mmp;
75 }
76 //assert(0);
77 return 0;
78 }
79
80
setCurrentMesh(int new_curr_id)81 void MeshDocument::setCurrentMesh( int new_curr_id)
82 {
83 if(new_curr_id<0)
84 {
85 currentMesh=0;
86 return;
87 }
88 currentMesh = getMesh(new_curr_id);
89 emit currentMeshChanged(new_curr_id);
90 assert(currentMesh);
91 }
92
93 //returns the raster at a given position in the list
getRaster(int i)94 RasterModel *MeshDocument::getRaster(int i)
95 {
96 foreach(RasterModel *rmp, rasterList)
97 {
98 if(rmp->id() == i) return rmp;
99 }
100 //assert(0);
101 return 0;
102 }
103
104 //if i is <0 it means that no currentRaster is set
setCurrentRaster(int new_curr_id)105 void MeshDocument::setCurrentRaster( int new_curr_id)
106 {
107 if(new_curr_id<0)
108 {
109 currentRaster=0;
110 return;
111 }
112
113 foreach(RasterModel *rmp, rasterList)
114 {
115 if(rmp->id() == new_curr_id)
116 {
117 currentRaster = rmp;
118 return;
119 }
120 }
121 assert(0);
122 }
123
requestUpdatingPerMeshDecorators(int mesh_id)124 void MeshDocument::requestUpdatingPerMeshDecorators(int mesh_id)
125 {
126 emit updateDecorators(mesh_id);
127 }
128
129 template <class LayerElement>
NameDisambiguator(QList<LayerElement * > & elemList,QString meshLabel)130 QString NameDisambiguator(QList<LayerElement*> &elemList, QString meshLabel )
131 {
132 QString newName=std::move(meshLabel);
133 typename QList<LayerElement*>::iterator mmi;
134
135 for(mmi=elemList.begin(); mmi!=elemList.end(); ++mmi)
136 {
137 if((*mmi)->label() == newName) // if duplicated name found
138 {
139 QFileInfo fi((*mmi)->label());
140 QString baseName = fi.baseName(); // all characters in the file up to the first '.' Eg "/tmp/archive.tar.gz" -> "archive"
141 QString suffix = fi.suffix();
142 bool ok;
143
144 // if name ends with a number between parenthesis (XXX),
145 // it was himself a duplicated name, and we need to
146 // just increase the number between parenthesis
147 int numDisamb;
148 int startDisamb;
149 int endDisamb;
150
151 startDisamb = baseName.lastIndexOf("(");
152 endDisamb = baseName.lastIndexOf(")");
153 if((startDisamb!=-1)&&(endDisamb!=-1))
154 numDisamb = (baseName.mid((startDisamb+1),(endDisamb-startDisamb-1))).toInt(&ok);
155 else
156 numDisamb = 0;
157
158 if(startDisamb!=-1)
159 newName = baseName.left(startDisamb)+ "(" + QString::number(numDisamb+1) + ")";
160 else
161 newName = baseName + "(" + QString::number(numDisamb+1) + ")";
162
163 if (suffix != QString(""))
164 newName = newName + "." + suffix;
165
166 // now recurse to see if the new name is free
167 newName = NameDisambiguator(elemList, newName);
168 }
169 }
170 return newName;
171 }
172
173
addNewMesh(QString fullPath,QString label,bool setAsCurrent)174 MeshModel * MeshDocument::addNewMesh(QString fullPath, QString label, bool setAsCurrent)
175 {
176 QString newlabel = NameDisambiguator(this->meshList,std::move(label));
177
178 if(!fullPath.isEmpty())
179 {
180 QFileInfo fi(fullPath);
181 fullPath = fi.absoluteFilePath();
182 }
183
184 MeshModel *newMesh = new MeshModel(this,fullPath,newlabel);
185 meshList.push_back(newMesh);
186
187 if(setAsCurrent)
188 this->setCurrentMesh(newMesh->id());
189
190 emit meshSetChanged();
191 emit meshAdded(newMesh->id());
192 return newMesh;
193 }
194
addOrGetMesh(QString fullPath,const QString & label,bool setAsCurrent)195 MeshModel * MeshDocument::addOrGetMesh(QString fullPath, const QString& label, bool setAsCurrent)
196 {
197 MeshModel *newMesh = getMesh(label);
198 if(newMesh) {
199 if(setAsCurrent)
200 this->setCurrentMesh(newMesh->id());
201 return newMesh;
202 }
203 return addNewMesh(std::move(fullPath),label,setAsCurrent);
204 }
205
delMesh(MeshModel * mmToDel)206 bool MeshDocument::delMesh(MeshModel *mmToDel)
207 {
208 if(!meshList.removeOne(mmToDel))
209 return false;
210 if((currentMesh == mmToDel) && (!meshList.empty()))
211 setCurrentMesh(this->meshList.at(0)->id());
212 else if (meshList.empty())
213 setCurrentMesh(-1);
214
215 int index = mmToDel->id();
216 delete mmToDel;
217
218 emit meshSetChanged();
219 emit meshRemoved(index);
220 return true;
221 }
222
addNewRaster()223 RasterModel * MeshDocument::addNewRaster(/*QString fullPathFilename*/)
224 {
225 QFileInfo info(fullPathFilename);
226 QString newLabel=info.fileName();
227 QString newName = NameDisambiguator(this->rasterList, newLabel);
228
229 RasterModel *newRaster=new RasterModel(this, newLabel);
230 rasterList.push_back(newRaster);
231
232 //Add new plane
233 //Plane *plane = new Plane(newRaster, fullPathFilename, QString());
234 //newRaster->addPlane(plane);
235
236 this->setCurrentRaster(newRaster->id());
237
238 emit rasterSetChanged();
239 return newRaster;
240 }
241
delRaster(RasterModel * rasterToDel)242 bool MeshDocument::delRaster(RasterModel *rasterToDel)
243 {
244 QMutableListIterator<RasterModel *> i(rasterList);
245
246 while (i.hasNext())
247 {
248 RasterModel *r = i.next();
249
250 if (r==rasterToDel)
251 {
252 i.remove();
253 delete rasterToDel;
254 }
255 }
256
257 if(currentRaster == rasterToDel)
258 {
259 if (!rasterList.empty())
260 setCurrentRaster(rasterList.at(0)->id());
261 else
262 setCurrentRaster(-1);
263 }
264 emit rasterSetChanged();
265
266 return true;
267 }
268
hasBeenModified()269 bool MeshDocument::hasBeenModified()
270 {
271 foreach(MeshModel *m, meshList)
272 if(m->meshModified()) return true;
273 return false;
274 }
275
276 //void MeshDocument::updateRenderStateMeshes(const QList<int>& mm,const int meshupdatemask)
277 //{
278 // static QTime currTime = QTime::currentTime();
279 // if(currTime.elapsed()< 100)
280 // return;
281 // for (QList<int>::const_iterator mit = mm.begin();mit != mm.end();++mit)
282 // {
283 // MeshModel* mesh = getMesh(*mit);
284 // if (mesh != NULL)
285 // mesh->bor.update(mesh->cm,meshupdatemask);
286 // }
287 // if ((mm.size() > 0) && (meshupdatemask != MeshModel::MM_NONE))
288 // emit documentUpdated();
289 // currTime.start();
290 //}
291
292 //void MeshDocument::updateRenderStateRasters(const QList<int>& rm,const int rasterupdatemask)
293 //{
294 // static QTime currTime = QTime::currentTime();
295 // if(currTime.elapsed()< 100)
296 // return;
297 // for (QList<int>::const_iterator rit = rm.begin();rit != rm.end();++rit)
298 // {
299 // RasterModel* raster = getRaster(*rit);
300 //
301 // /**********READD*****/
302 // /* if (raster != NULL)
303 // renderState().update(raster->id(),*raster,rasterupdatemask);*/
304 // /********************/
305 // }
306 // if ((rm.size() > 0) && (rasterupdatemask != RasterModel::RM_NONE))
307 // emit documentUpdated();
308 // currTime.start();
309 //}
310 //
311 //void MeshDocument::updateRenderState(const QList<int>& mm,const int meshupdatemask,const QList<int>& rm,const int rasterupdatemask)
312 //{
313 // static QTime currTime = QTime::currentTime();
314 // if(currTime.elapsed()< 100)
315 // return;
316 // /* for (QList<int>::const_iterator mit = mm.begin();mit != mm.end();++mit)
317 // {
318 // MeshModel* mesh = getMesh(*mit);
319 // if (mesh != NULL)
320 // renderState().update(mesh->id(),mesh->cm,meshupdatemask);
321 // }
322 // for (QList<int>::const_iterator rit = rm.begin();rit != rm.end();++rit)
323 // {
324 // RasterModel* raster = getRaster(*rit);
325 // if (raster != NULL)
326 // renderState().update(raster->id(),*raster,rasterupdatemask);
327 // }*/
328 // if (((mm.size() > 0) && (meshupdatemask != MeshModel::MM_NONE)) || (rm.size() > 0 && (rasterupdatemask != RasterModel::RM_NONE)))
329 // emit documentUpdated();
330 // currTime.start();
331 //}
332
MeshDocument()333 MeshDocument::MeshDocument()
334 {
335 meshIdCounter=0;
336 rasterIdCounter=0;
337 currentMesh = 0;
338 currentRaster = 0;
339 busy=false;
340 filterHistory = new FilterScript();
341 }
342
343
Clear()344 void MeshModel::Clear()
345 {
346 meshModified() = false;
347 // These data are always active on the mesh
348 currentDataMask = MM_NONE;
349 currentDataMask |= MM_VERTCOORD | MM_VERTNORMAL | MM_VERTFLAG ;
350 currentDataMask |= MM_FACEVERT | MM_FACENORMAL | MM_FACEFLAG ;
351
352 visible=true;
353 cm.Tr.SetIdentity();
354 cm.sfn=0;
355 cm.svn=0;
356 }
357
UpdateBoxAndNormals()358 void MeshModel::UpdateBoxAndNormals()
359 {
360 tri::UpdateBounding<CMeshO>::Box(cm);
361 if(cm.fn>0) {
362 tri::UpdateNormal<CMeshO>::PerFaceNormalized(cm);
363 tri::UpdateNormal<CMeshO>::PerVertexAngleWeighted(cm);
364 }
365 }
366
MeshModel(MeshDocument * _parent,const QString & fullFileName,const QString & labelName)367 MeshModel::MeshModel(MeshDocument *_parent, const QString& fullFileName, const QString& labelName)
368 {
369 /*glw.m = &(cm);*/
370 Clear();
371 parent=_parent;
372 _id=parent->newMeshId();
373 if(!fullFileName.isEmpty()) this->fullPathFileName=fullFileName;
374 if(!labelName.isEmpty()) this->_label=labelName;
375 }
376
MeshModel(MeshModel * cp)377 MeshModel::MeshModel(MeshModel* cp)
378 {
379 if (cp == NULL)
380 return;
381 parent = cp->parent;
382 if (parent != NULL)
383 _id = parent->newMeshId();
384 cm.Tr = cp->cm.Tr;
385 cm.sfn = cp->cm.sfn;
386 cm.svn = cp->cm.svn;
387 visible = cp->visible;
388 updateDataMask(cp->currentDataMask);
389 vcg::tri::Append<CMeshO, CMeshO>::MeshCopy(cm, cp->cm);
390 }
391
relativePathName() const392 QString MeshModel::relativePathName() const
393 {
394 QDir documentDir (documentPathName());
395 QString relPath=documentDir.relativeFilePath(this->fullPathFileName);
396
397 if(relPath.size()>1 && relPath[0]=='.' && relPath[1]=='.')
398 qDebug("Error we have a mesh that is not in the same folder of the project: %s ", qUtf8Printable(relPath));
399
400 return relPath;
401 }
402
documentPathName() const403 QString MeshModel::documentPathName() const
404 {
405 return parent->pathName();
406 }
407
io2mm(int single_iobit)408 int MeshModel::io2mm(int single_iobit)
409 {
410 switch(single_iobit)
411 {
412 case tri::io::Mask::IOM_NONE : return MM_NONE;
413 case tri::io::Mask::IOM_VERTCOORD : return MM_VERTCOORD;
414 case tri::io::Mask::IOM_VERTCOLOR : return MM_VERTCOLOR;
415 case tri::io::Mask::IOM_VERTFLAGS : return MM_VERTFLAG;
416 case tri::io::Mask::IOM_VERTQUALITY : return MM_VERTQUALITY;
417 case tri::io::Mask::IOM_VERTNORMAL : return MM_VERTNORMAL;
418 case tri::io::Mask::IOM_VERTTEXCOORD : return MM_VERTTEXCOORD;
419 case tri::io::Mask::IOM_VERTRADIUS : return MM_VERTRADIUS;
420
421 case tri::io::Mask::IOM_FACEINDEX : return MM_FACEVERT ;
422 case tri::io::Mask::IOM_FACEFLAGS : return MM_FACEFLAG ;
423 case tri::io::Mask::IOM_FACECOLOR : return MM_FACECOLOR ;
424 case tri::io::Mask::IOM_FACEQUALITY : return MM_FACEQUALITY;
425 case tri::io::Mask::IOM_FACENORMAL : return MM_FACENORMAL ;
426
427 case tri::io::Mask::IOM_WEDGTEXCOORD : return MM_WEDGTEXCOORD;
428 case tri::io::Mask::IOM_WEDGCOLOR : return MM_WEDGCOLOR;
429 case tri::io::Mask::IOM_WEDGNORMAL : return MM_WEDGNORMAL ;
430
431 case tri::io::Mask::IOM_BITPOLYGONAL : return MM_POLYGONAL ;
432
433 default:
434 assert(0);
435 return MM_NONE; // FIXME: Returning this is not the best solution (!)
436 break;
437 } ;
438 }
439
Plane(const Plane & pl)440 Plane::Plane(const Plane& pl)
441 {
442 semantic = pl.semantic;
443 fullPathFileName = pl.fullPathFileName;
444 image = QImage(pl.image);
445 }
446
Plane(const QString & pathName,const int _semantic)447 Plane::Plane(const QString& pathName, const int _semantic)
448 {
449 semantic =_semantic;
450 fullPathFileName = pathName;
451
452 image = QImage(pathName);
453 }
454
RasterModel(MeshDocument * parent,QString _rasterName)455 RasterModel::RasterModel(MeshDocument *parent, QString _rasterName)
456 {
457 _id=parent->newRasterId();
458 par = parent;
459 this->_label= std::move(_rasterName);
460 visible=true;
461 }
462
RasterModel()463 RasterModel::RasterModel()
464 {
465
466 }
467
468
MeshLabRenderRaster()469 MeshLabRenderRaster::MeshLabRenderRaster()
470 {
471
472 }
473
MeshLabRenderRaster(const MeshLabRenderRaster & rm)474 MeshLabRenderRaster::MeshLabRenderRaster( const MeshLabRenderRaster& rm )
475 :shot(rm.shot)
476 {
477 for(QList<Plane*>::const_iterator it = rm.planeList.begin();it != rm.planeList.end();++it)
478 {
479 planeList.push_back(new Plane(**it));
480 if (rm.currentPlane == *it)
481 currentPlane = planeList[planeList.size() - 1];
482 }
483 }
484
addPlane(Plane * plane)485 void MeshLabRenderRaster::addPlane(Plane *plane)
486 {
487 planeList.append(plane);
488 currentPlane = plane;
489 }
490
~MeshLabRenderRaster()491 MeshLabRenderRaster::~MeshLabRenderRaster()
492 {
493 currentPlane = NULL;
494 for(int ii = 0;ii < planeList.size();++ii)
495 delete planeList[ii];
496 }
497
create(int _mask,MeshModel * _m)498 void MeshModelState::create(int _mask, MeshModel* _m)
499 {
500 m=_m;
501 changeMask=_mask;
502 if(changeMask & MeshModel::MM_VERTCOLOR)
503 {
504 vertColor.resize(m->cm.vert.size());
505 std::vector<Color4b>::iterator ci;
506 CMeshO::VertexIterator vi;
507 for(vi = m->cm.vert.begin(), ci = vertColor.begin(); vi != m->cm.vert.end(); ++vi, ++ci)
508 if(!(*vi).IsD()) (*ci)=(*vi).C();
509 }
510
511 if(changeMask & MeshModel::MM_VERTQUALITY)
512 {
513 vertQuality.resize(m->cm.vert.size());
514 std::vector<float>::iterator qi;
515 CMeshO::VertexIterator vi;
516 for(vi = m->cm.vert.begin(), qi = vertQuality.begin(); vi != m->cm.vert.end(); ++vi, ++qi)
517 if(!(*vi).IsD()) (*qi)=(*vi).Q();
518 }
519
520 if(changeMask & MeshModel::MM_VERTCOORD)
521 {
522 vertCoord.resize(m->cm.vert.size());
523 std::vector<Point3m>::iterator ci;
524 CMeshO::VertexIterator vi;
525 for(vi = m->cm.vert.begin(), ci = vertCoord.begin(); vi != m->cm.vert.end(); ++vi, ++ci)
526 if(!(*vi).IsD()) (*ci)=(*vi).P();
527 }
528
529 if(changeMask & MeshModel::MM_VERTNORMAL)
530 {
531 vertNormal.resize(m->cm.vert.size());
532 std::vector<Point3m>::iterator ci;
533 CMeshO::VertexIterator vi;
534 for(vi = m->cm.vert.begin(), ci = vertNormal.begin(); vi != m->cm.vert.end(); ++vi, ++ci)
535 if(!(*vi).IsD()) (*ci)=(*vi).N();
536 }
537
538 if(changeMask & MeshModel::MM_FACENORMAL)
539 {
540 faceNormal.resize(m->cm.face.size());
541 std::vector<Point3m>::iterator ci;
542 CMeshO::FaceIterator fi;
543 for(fi = m->cm.face.begin(), ci = faceNormal.begin(); fi != m->cm.face.end(); ++fi, ++ci)
544 if(!(*fi).IsD()) (*ci) = (*fi).N();
545 }
546
547 if(changeMask & MeshModel::MM_FACECOLOR)
548 {
549 m->updateDataMask(MeshModel::MM_FACECOLOR);
550 faceColor.resize(m->cm.face.size());
551 std::vector<Color4b>::iterator ci;
552 CMeshO::FaceIterator fi;
553 for(fi = m->cm.face.begin(), ci = faceColor.begin(); fi != m->cm.face.end(); ++fi, ++ci)
554 if(!(*fi).IsD()) (*ci) = (*fi).C();
555 }
556
557 if(changeMask & MeshModel::MM_FACEFLAGSELECT)
558 {
559 faceSelection.resize(m->cm.face.size());
560 std::vector<bool>::iterator ci;
561 CMeshO::FaceIterator fi;
562 for(fi = m->cm.face.begin(), ci = faceSelection.begin(); fi != m->cm.face.end(); ++fi, ++ci)
563 if(!(*fi).IsD()) (*ci) = (*fi).IsS();
564 }
565
566 if(changeMask & MeshModel::MM_VERTFLAGSELECT)
567 {
568 vertSelection.resize(m->cm.vert.size());
569 std::vector<bool>::iterator ci;
570 CMeshO::VertexIterator vi;
571 for(vi = m->cm.vert.begin(), ci = vertSelection.begin(); vi != m->cm.vert.end(); ++vi, ++ci)
572 if(!(*vi).IsD()) (*ci) = (*vi).IsS();
573 }
574
575 if(changeMask & MeshModel::MM_TRANSFMATRIX)
576 Tr = m->cm.Tr;
577 if(changeMask & MeshModel::MM_CAMERA)
578 this->shot = m->cm.shot;
579 }
580
apply(MeshModel * _m)581 bool MeshModelState::apply(MeshModel *_m)
582 {
583 if(_m != m)
584 return false;
585 if(changeMask & MeshModel::MM_VERTCOLOR)
586 {
587 if(vertColor.size() != m->cm.vert.size()) return false;
588 std::vector<Color4b>::iterator ci;
589 CMeshO::VertexIterator vi;
590 for(vi = m->cm.vert.begin(), ci = vertColor.begin(); vi != m->cm.vert.end(); ++vi, ++ci)
591 if(!(*vi).IsD()) (*vi).C()=(*ci);
592 }
593 if(changeMask & MeshModel::MM_FACECOLOR)
594 {
595 if(faceColor.size() != m->cm.face.size()) return false;
596 std::vector<Color4b>::iterator ci;
597 CMeshO::FaceIterator fi;
598 for(fi = m->cm.face.begin(), ci = faceColor.begin(); fi != m->cm.face.end(); ++fi, ++ci)
599 if(!(*fi).IsD()) (*fi).C()=(*ci);
600 }
601 if(changeMask & MeshModel::MM_VERTQUALITY)
602 {
603 if(vertQuality.size() != m->cm.vert.size()) return false;
604 std::vector<float>::iterator qi;
605 CMeshO::VertexIterator vi;
606 for(vi = m->cm.vert.begin(), qi = vertQuality.begin(); vi != m->cm.vert.end(); ++vi, ++qi)
607 if(!(*vi).IsD()) (*vi).Q()=(*qi);
608 }
609
610 if(changeMask & MeshModel::MM_VERTCOORD)
611 {
612 if(vertCoord.size() != m->cm.vert.size())
613 return false;
614 std::vector<Point3m>::iterator ci;
615 CMeshO::VertexIterator vi;
616 for(vi = m->cm.vert.begin(), ci = vertCoord.begin(); vi != m->cm.vert.end(); ++vi, ++ci)
617 if(!(*vi).IsD())
618 (*vi).P()=(*ci);
619 }
620
621 if(changeMask & MeshModel::MM_VERTNORMAL)
622 {
623 if(vertNormal.size() != m->cm.vert.size()) return false;
624 std::vector<Point3m>::iterator ci;
625 CMeshO::VertexIterator vi;
626 for(vi = m->cm.vert.begin(), ci=vertNormal.begin(); vi != m->cm.vert.end(); ++vi, ++ci)
627 if(!(*vi).IsD()) (*vi).N()=(*ci);
628 }
629
630 if(changeMask & MeshModel::MM_FACENORMAL)
631 {
632 if(faceNormal.size() != m->cm.face.size()) return false;
633 std::vector<Point3m>::iterator ci;
634 CMeshO::FaceIterator fi;
635 for(fi = m->cm.face.begin(), ci=faceNormal.begin(); fi != m->cm.face.end(); ++fi, ++ci)
636 if(!(*fi).IsD()) (*fi).N()=(*ci);
637 }
638
639 if(changeMask & MeshModel::MM_FACEFLAGSELECT)
640 {
641 if(faceSelection.size() != m->cm.face.size()) return false;
642 std::vector<bool>::iterator ci;
643 CMeshO::FaceIterator fi;
644 for(fi = m->cm.face.begin(), ci = faceSelection.begin(); fi != m->cm.face.end(); ++fi, ++ci)
645 {
646 if((*ci))
647 (*fi).SetS();
648 else
649 (*fi).ClearS();
650 }
651 }
652
653 if(changeMask & MeshModel::MM_VERTFLAGSELECT)
654 {
655 if(vertSelection.size() != m->cm.vert.size()) return false;
656 std::vector<bool>::iterator ci;
657 CMeshO::VertexIterator vi;
658 for(vi = m->cm.vert.begin(), ci = vertSelection.begin(); vi != m->cm.vert.end(); ++vi, ++ci)
659 {
660 if((*ci))
661 (*vi).SetS();
662 else
663 (*vi).ClearS();
664 }
665 }
666
667
668 if(changeMask & MeshModel::MM_TRANSFMATRIX)
669 m->cm.Tr=Tr;
670 if(changeMask & MeshModel::MM_CAMERA)
671 m->cm.shot = this->shot;
672
673 return true;
674 }
675
676 /**** DATAMASK STUFF ****/
677
setVisible(int meshId,bool val)678 void MeshDocument::setVisible(int meshId, bool val)
679 {
680 getMesh(meshId)->visible=val;
681 emit meshSetChanged();
682 }
683
hasDataMask(const int maskToBeTested) const684 bool MeshModel::hasDataMask(const int maskToBeTested) const
685 {
686 return ((currentDataMask & maskToBeTested)!= 0);
687 }
updateDataMask(MeshModel * m)688 void MeshModel::updateDataMask(MeshModel *m)
689 {
690 updateDataMask(m->currentDataMask);
691 }
692
updateDataMask(int neededDataMask)693 void MeshModel::updateDataMask(int neededDataMask)
694 {
695 if((neededDataMask & MM_FACEFACETOPO)!=0)
696 {
697 cm.face.EnableFFAdjacency();
698 tri::UpdateTopology<CMeshO>::FaceFace(cm);
699 }
700 if((neededDataMask & MM_VERTFACETOPO)!=0)
701 {
702 cm.vert.EnableVFAdjacency();
703 cm.face.EnableVFAdjacency();
704 tri::UpdateTopology<CMeshO>::VertexFace(cm);
705 }
706
707 if((neededDataMask & MM_WEDGTEXCOORD)!=0)
708 cm.face.EnableWedgeTexCoord();
709 if((neededDataMask & MM_FACECOLOR)!=0)
710 cm.face.EnableColor();
711 if((neededDataMask & MM_FACEQUALITY)!=0)
712 cm.face.EnableQuality();
713 if((neededDataMask & MM_FACECURVDIR)!=0)
714 cm.face.EnableCurvatureDir();
715 if((neededDataMask & MM_FACEMARK)!=0)
716 cm.face.EnableMark();
717 if((neededDataMask & MM_VERTMARK)!=0)
718 cm.vert.EnableMark();
719 if((neededDataMask & MM_VERTCURV)!=0)
720 cm.vert.EnableCurvature();
721 if((neededDataMask & MM_VERTCURVDIR)!=0)
722 cm.vert.EnableCurvatureDir();
723 if((neededDataMask & MM_VERTRADIUS)!=0)
724 cm.vert.EnableRadius();
725 if((neededDataMask & MM_VERTTEXCOORD)!=0)
726 cm.vert.EnableTexCoord();
727
728 currentDataMask |= neededDataMask;
729 }
730
clearDataMask(int unneededDataMask)731 void MeshModel::clearDataMask(int unneededDataMask)
732 {
733 if( ( (unneededDataMask & MM_VERTFACETOPO)!=0) && hasDataMask(MM_VERTFACETOPO)) {cm.face.DisableVFAdjacency();
734 cm.vert.DisableVFAdjacency(); }
735 if( ( (unneededDataMask & MM_FACEFACETOPO)!=0) && hasDataMask(MM_FACEFACETOPO)) cm.face.DisableFFAdjacency();
736
737 if( ( (unneededDataMask & MM_WEDGTEXCOORD)!=0) && hasDataMask(MM_WEDGTEXCOORD)) cm.face.DisableWedgeTexCoord();
738 if( ( (unneededDataMask & MM_FACECOLOR)!=0) && hasDataMask(MM_FACECOLOR)) cm.face.DisableColor();
739 if( ( (unneededDataMask & MM_FACEQUALITY)!=0) && hasDataMask(MM_FACEQUALITY)) cm.face.DisableQuality();
740 if( ( (unneededDataMask & MM_FACEMARK)!=0) && hasDataMask(MM_FACEMARK)) cm.face.DisableMark();
741 if( ( (unneededDataMask & MM_VERTMARK)!=0) && hasDataMask(MM_VERTMARK)) cm.vert.DisableMark();
742 if( ( (unneededDataMask & MM_VERTCURV)!=0) && hasDataMask(MM_VERTCURV)) cm.vert.DisableCurvature();
743 if( ( (unneededDataMask & MM_VERTCURVDIR)!=0) && hasDataMask(MM_VERTCURVDIR)) cm.vert.DisableCurvatureDir();
744 if( ( (unneededDataMask & MM_VERTRADIUS)!=0) && hasDataMask(MM_VERTRADIUS)) cm.vert.DisableRadius();
745 if( ( (unneededDataMask & MM_VERTTEXCOORD)!=0) && hasDataMask(MM_VERTTEXCOORD)) cm.vert.DisableTexCoord();
746
747 currentDataMask = currentDataMask & (~unneededDataMask);
748 }
749
Enable(int openingFileMask)750 void MeshModel::Enable(int openingFileMask)
751 {
752 if( openingFileMask & tri::io::Mask::IOM_VERTTEXCOORD )
753 updateDataMask(MM_VERTTEXCOORD);
754 if( openingFileMask & tri::io::Mask::IOM_WEDGTEXCOORD )
755 updateDataMask(MM_WEDGTEXCOORD);
756 if( openingFileMask & tri::io::Mask::IOM_VERTCOLOR )
757 updateDataMask(MM_VERTCOLOR);
758 if( openingFileMask & tri::io::Mask::IOM_FACECOLOR )
759 updateDataMask(MM_FACECOLOR);
760 if( openingFileMask & tri::io::Mask::IOM_VERTRADIUS ) updateDataMask(MM_VERTRADIUS);
761 if( openingFileMask & tri::io::Mask::IOM_CAMERA ) updateDataMask(MM_CAMERA);
762 if( openingFileMask & tri::io::Mask::IOM_VERTQUALITY ) updateDataMask(MM_VERTQUALITY);
763 if( openingFileMask & tri::io::Mask::IOM_FACEQUALITY ) updateDataMask(MM_FACEQUALITY);
764 if( openingFileMask & tri::io::Mask::IOM_BITPOLYGONAL ) updateDataMask(MM_POLYGONAL);
765 }
766
meshModified()767 bool& MeshModel::meshModified()
768 {
769 return this->modified;
770 }
771
dataMask() const772 int MeshModel::dataMask() const
773 {
774 return currentDataMask;
775 }
776
MeshDocumentStateData()777 MeshDocumentStateData::MeshDocumentStateData()
778 :_lock(QReadWriteLock::Recursive)
779 {
780
781 }
782
~MeshDocumentStateData()783 MeshDocumentStateData::~MeshDocumentStateData()
784 {
785 QWriteLocker locker(&_lock);
786 _existingmeshesbeforeoperation.clear();
787 }
788
create(MeshDocument & md)789 void MeshDocumentStateData::create(MeshDocument& md)
790 {
791 QWriteLocker locker(&_lock);
792 for (int ii = 0; ii < md.meshList.size(); ++ii)
793 {
794 MeshModel* mm = md.meshList[ii];
795 if (mm != NULL)
796 insert(mm->id(), MeshModelStateData(mm->dataMask(), mm->cm.VN(), mm->cm.FN(), mm->cm.EN()));
797 }
798 }
799
insert(const int key,const MeshModelStateData & value)800 QMap<int, MeshModelStateData>::iterator MeshDocumentStateData::insert(const int key, const MeshModelStateData & value)
801 {
802 QWriteLocker locker(&_lock);
803 return _existingmeshesbeforeoperation.insert(key,value);
804 }
805
find(const int key)806 QMap<int, MeshModelStateData>::iterator MeshDocumentStateData::find(const int key)
807 {
808 QReadLocker locker(&_lock);
809 return _existingmeshesbeforeoperation.find(key);
810 }
811
begin()812 QMap<int, MeshModelStateData>::iterator MeshDocumentStateData::begin()
813 {
814 QReadLocker locker(&_lock);
815 return _existingmeshesbeforeoperation.begin();
816 }
817
end()818 QMap<int, MeshModelStateData>::iterator MeshDocumentStateData::end()
819 {
820 QReadLocker locker(&_lock);
821 return _existingmeshesbeforeoperation.end();
822 }
823
clear()824 void MeshDocumentStateData::clear()
825 {
826 QWriteLocker locker(&_lock);
827 _existingmeshesbeforeoperation.clear();
828 }
829