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