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 #ifndef MESHMODEL_H
25 #define MESHMODEL_H
26 #include <GL/glew.h>
27 
28 #include <stdio.h>
29 #include <time.h>
30 #include <map>
31 
32 #include "ml_mesh_type.h"
33 
34 #include <vcg/complex/algorithms/update/bounding.h>
35 #include <vcg/complex/algorithms/update/color.h>
36 #include <vcg/complex/algorithms/update/flag.h>
37 #include <vcg/complex/algorithms/update/normal.h>
38 #include <vcg/complex/algorithms/update/position.h>
39 #include <vcg/complex/algorithms/update/quality.h>
40 #include <vcg/complex/algorithms/update/selection.h>
41 #include <vcg/complex/algorithms/update/topology.h>
42 
43 
44 //#include <wrap/gl/trimesh.h>
45 
46 
47 
48 #include <wrap/callback.h>
49 #include <wrap/io_trimesh/io_mask.h>
50 #include <wrap/io_trimesh/additionalinfo.h>
51 
52 #include <QList>
53 #include <QString>
54 #include <QStringList>
55 #include <QFileInfo>
56 #include <QReadWriteLock>
57 #include <QImage>
58 #include <QAction>
59 #include "GLLogStream.h"
60 #include "filterscript.h"
61 #include "ml_shared_data_context.h"
62 
63 
64 /*
65 MeshModel Class
66 The base class for representing a single mesh.
67 It contains a single vcg mesh object with some additional information for keeping track of its origin and of what info it has.
68 */
69 
70 class MeshDocument;
71 
72 class MeshModel
73 {
74 public:
75     /*
76     This enum specify the various simplex components
77     It is used in various parts of the framework:
78     - to know what elements are currently active and therefore can be saved on a file
79     - to know what elements are required by a filter and therefore should be made ready before starting the filter (e.g. if a
80     - to know what elements are changed by a filter and therefore should be saved/restored in case of dynamic filters with a preview
81     */
82     enum MeshElement{
83         MM_NONE             = 0x00000000,
84         MM_VERTCOORD        = 0x00000001,
85         MM_VERTNORMAL       = 0x00000002,
86         MM_VERTFLAG         = 0x00000004,
87         MM_VERTCOLOR        = 0x00000008,
88         MM_VERTQUALITY      = 0x00000010,
89         MM_VERTMARK	        = 0x00000020,
90         MM_VERTFACETOPO     = 0x00000040,
91         MM_VERTCURV	        = 0x00000080,
92         MM_VERTCURVDIR      = 0x00000100,
93         MM_VERTRADIUS       = 0x00000200,
94         MM_VERTTEXCOORD     = 0x00000400,
95         MM_VERTNUMBER       = 0x00000800,
96 
97         MM_FACEVERT         = 0x00001000,
98         MM_FACENORMAL       = 0x00002000,
99         MM_FACEFLAG	        = 0x00004000,
100         MM_FACECOLOR        = 0x00008000,
101         MM_FACEQUALITY      = 0x00010000,
102         MM_FACEMARK	        = 0x00020000,
103         MM_FACEFACETOPO     = 0x00040000,
104         MM_FACENUMBER       = 0x00080000,
105         MM_FACECURVDIR      = 0x00100000,
106 
107         MM_WEDGTEXCOORD     = 0x00200000,
108         MM_WEDGNORMAL       = 0x00400000,
109         MM_WEDGCOLOR        = 0x00800000,
110 
111         // 	Selection
112         MM_VERTFLAGSELECT   = 0x01000000,
113         MM_FACEFLAGSELECT   = 0x02000000,
114 
115         // Per Mesh Stuff....
116         MM_CAMERA			= 0x08000000,
117         MM_TRANSFMATRIX     = 0x10000000,
118         MM_COLOR            = 0x20000000,
119         MM_POLYGONAL        = 0x40000000,
120 
121 		// unknown - will raise exceptions, to be avoided, here just for compatibility
122         MM_UNKNOWN          = 0x80000000,
123 
124 		// geometry change (for filters that remove stuff or modify geometry or topology, but not touch face/vertex color or face/vertex quality)
125 		MM_GEOMETRY_AND_TOPOLOGY_CHANGE  = 0x431e7be7,
126 
127 		// everything - dangerous, will add unwanted data to layer (e.g. if you use MM_ALL it could means that it could add even color or quality)
128         MM_ALL				= 0xffffffff
129     };
130 
131     MeshModel(MeshDocument *parent, const QString& fullFileName, const QString& labelName);
132 	MeshModel(MeshModel* cp);
~MeshModel()133     ~MeshModel()
134     {
135     }
136 
137 	MeshDocument *parent;
138 
139     CMeshO cm;
140 
141 
142 
143 
144     /*vcg::GlTrimesh<CMeshO> glw;*/
145 
146 
147 
148     /*
149     Bitmask denoting what fields are currently used in the mesh
150     it is composed by MeshElement enums.
151     it should be changed by only mean the following functions:
152 
153     updateDataMask(neededStuff)
154     clearDataMask(no_needed_stuff)
155     hasDataMask(stuff)
156 
157     Note that if an element is active means that is also allocated
158     Some unactive elements (vertex color) are usually already allocated
159     other elements (FFAdj or curvature data) not necessarily.
160 
161     */
162 
163 private:
164     int currentDataMask;
165     QString fullPathFileName;
166     QString _label;
167     int _id;
168     bool modified;
169 
170 public:
171     void Clear();
172     void UpdateBoxAndNormals(); // This is the STANDARD method that you should call after changing coords.
id()173     inline int id() const {return _id;}
174 
175 
176     // Some notes about the files and naming.
177     // Each mesh when shown in the layer dialog has a label.
178     // By default the label is just the name of the file, but the
179 
180     // in a future the path should be moved outside the meshmodel into the meshdocument (and assume that all the meshes resides in a common subtree)
181     // currently we just fix the interface and make the pathname private for avoiding future hassles.
182 
label()183     QString label() const { if(_label.isEmpty()) return shortName(); else return _label;}
184 
185     /// The whole full path name of the mesh
fullName()186     QString fullName() const {return fullPathFileName;}
187 
188     /// just the name of the file
shortName()189     QString shortName() const { return QFileInfo(fullPathFileName).fileName(); }
190 
191     /// the full path without the name of the file (e.g. the dir where the mesh and often its textures are)
pathName()192     QString pathName() const {QFileInfo fi(fullName()); return fi.absolutePath();}
193 
194     /// just the extension.
suffixName()195     QString suffixName() const {QFileInfo fi(fullName()); return fi.suffix();}
196 
197     /// the relative path with respect to the current project
198     QString relativePathName() const;
199 
200     /// the absolute path of the current project
201     QString documentPathName() const;
202 
setFileName(QString newFileName)203     void setFileName(QString newFileName) {
204         QFileInfo fi(newFileName);
205         if(!fi.isAbsolute()) qWarning("Someone is trying to put a non relative filename");
206         fullPathFileName = fi.absoluteFilePath();
207     }
setLabel(QString newName)208     void setLabel(QString newName) {_label=newName;}
209 
210     bool visible; // used in rendering; Needed for toggling on and off the meshes
isVisible()211     bool isVisible() { return visible; }
212 
213     // This function is roughly equivalent to the updateDataMask,
214     // but it takes in input a mask coming from a filetype instead of a filter requirement (like topology etc)
215     void Enable(int openingFileMask);
216 
217     bool hasDataMask(const int maskToBeTested) const;
218     void updateDataMask(MeshModel *m);
219     void updateDataMask(int neededDataMask);
220     void clearDataMask(int unneededDataMask);
221     int dataMask() const;
222 
223 
224     bool& meshModified();
225     static int io2mm(int single_iobit);
226 };// end class MeshModel
227 
228 
229 /*
230 Plane Class
231 the base class for a registered image that contains the path, the semantic and the data of the image
232 */
233 
234 class Plane
235 {
236 public:
237 
238     enum PlaneSemantic
239     {
240       NONE        = 0x0000,
241       RGBA        = 0x0001,
242       MASK_UB     = 0x0002,
243       MASK_F      = 0x0004,
244       DEPTH_F     = 0x0008,
245       EXTRA00_F        = 0x0100,
246       EXTRA01_F        = 0x0200,
247       EXTRA02_F        = 0x0400,
248       EXTRA03_F        = 0x0800,
249       EXTRA00_RGBA     = 0x1000,
250       EXTRA01_RGBA     = 0x2000,
251       EXTRA02_RGBA     = 0x4000,
252       EXTRA03_RGBA     = 0x8000
253     };
254 
255     int semantic;
256     QString fullPathFileName;
257     QImage image;
258     QImage thumb;
259     float *buf;
260 
IsInCore()261     bool IsInCore() { return !image.isNull(); }
262     void Load();
263     void Discard(); //discard  the loaded image freeing the mem.
264 
265     /// The whole full path name of the mesh
fullName()266     const QString fullName() const {return fullPathFileName;}
267     /// just the name of the file
shortName()268     const QString shortName() const { return QFileInfo(fullPathFileName).fileName(); }
269 
270     Plane(const Plane& pl);
271     Plane(const QString& pathName, const int _semantic);
272 
273 }; //end class Plane
274 
275 
276 class MeshLabRenderRaster
277 {
278 public:
279     MeshLabRenderRaster();
280     MeshLabRenderRaster(const MeshLabRenderRaster& rm);
281     ~MeshLabRenderRaster();
282 
283     Shotm shot;
284 
285     ///The list of the registered images
286     QList<Plane *> planeList;
287     Plane *currentPlane;
288 
289     void addPlane(Plane * plane);
290 };
291 
292 /*
293 RasterModel Class
294 The base class for keeping a set of "registered" images (e.g. images that can be projected onto a 3D space).
295 Each Raster model is composed by a list of registered images, each image with its own "semantic" (color, depth, normals, quality, masks)
296 and with all the images sharing the same shot.
297 */
298 
299 class RasterModel : public MeshLabRenderRaster
300 {
301 public:
302     RasterModel();
303     MeshDocument* par;
304 
305 private:
306     int _id;
307     QString _label;
308 
309 public:
310     bool visible;
id()311     inline int id() const {return _id;}
312 
313     RasterModel(MeshDocument *parent, QString _rasterName=QString());
314 
setLabel(QString newLabel)315     void setLabel(QString newLabel) {_label = newLabel;}
316 
label()317     const QString label() const {
318         if(!_label.isEmpty())  return _label;
319         if(!planeList.empty()) return planeList.first()->shortName();
320         return "Error!";
321     }
322 
323     enum RasterElement
324     {
325         RM_NONE		= 0x00000000,
326         RM_ALL		= 0xffffffff
327     };
328 };// end class RasterModel
329 
330 //class RenderMode
331 //{
332 //private:
333 //    QList<QAction*> declist;
334 //
335 //public:
336 //    vcg::GLW::DrawMode	drawMode;
337 //    vcg::GLW::ColorMode	colorMode;
338 //    vcg::GLW::TextureMode	textureMode;
339 //
340 //
341 //
342 //    MLRenderingData::PRIMITIVE_MODALITY_MASK pmmask;
343 //    MLRenderingData::RendAtts atts;
344 //
345 //    bool lighting;
346 //    bool backFaceCull;
347 //    bool doubleSideLighting;
348 //    bool fancyLighting;
349 //
350 //    RenderMode(vcg::GLW::DrawMode dm) // :declist()
351 //    {
352 //      Init();
353 //      drawMode=dm;
354 //    }
355 //
356 //    RenderMode() {  Init(); }
357 //
358 //    void Init()
359 //    {
360 //        drawMode	= vcg::GLW::DMSmooth;
361 //        colorMode = vcg::GLW::CMNone;
362 //        textureMode = vcg::GLW::TMNone;
363 //
364 //        pmmask = MLRenderingData::PR_SOLID;
365 //        atts = MLRenderingData::RendAtts();
366 //        atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true;
367 //        atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true;
368 //
369 //        lighting = true;
370 //        backFaceCull = false;
371 //        doubleSideLighting = false;
372 //        fancyLighting = false;
373 //    }
374 //
375 //    inline void addPrimitiveModality(MLRenderingData::PRIMITIVE_MODALITY addedpm)
376 //    {
377 //        pmmask = pmmask | addedpm;
378 //    }
379 //
380 //    inline void removePrimitiveModality(MLRenderingData::PRIMITIVE_MODALITY removedpm)
381 //    {
382 //        pmmask = pmmask & (~removedpm);
383 //    }
384 //
385 //    inline void setDrawMode(const vcg::GLW::DrawMode dm)
386 //    {
387 //        drawMode = dm;
388 //    }
389 //
390 //    inline void setColorMode(const vcg::GLW::ColorMode cm)
391 //    {
392 //        colorMode = cm;
393 //    }
394 //
395 //    inline void setTextureMode(const vcg::GLW::TextureMode tm)
396 //    {
397 //        textureMode = tm;
398 //    }
399 //
400 //    inline void setLighting(const bool ison)
401 //    {
402 //        lighting = ison;
403 //    }
404 //
405 //    inline void setBackFaceCull(const bool ison)
406 //    {
407 //        backFaceCull = ison;
408 //    }
409 //
410 //    inline void setDoubleFaceLighting(const bool ison)
411 //    {
412 //        doubleSideLighting = ison;
413 //    }
414 //
415 //    inline void setFancyLighting(const bool ison)
416 //    {
417 //        fancyLighting = ison;
418 //    }
419 //
420 //    inline QList<QAction*>& decoratorList()
421 //    {
422 //        return declist;
423 //    }
424 //
425 //    static RenderMode defaultRenderingAtts();
426 //}; // end class RenderMode
427 //Q_DECLARE_METATYPE(RenderMode)
428 
429 //class RasterModelState : public QObject
430 //{
431 //	Q_OBJECT
432 //public:
433 //	MeshLabRenderState();
434 //	~MeshLabRenderState();
435 //
436 //private:
437 //	//for quickness I added a RasterModel, but should be something less.
438 //	QMap<int,RasterModel*> _rendermap;
439 //	QReadWriteLock _mutdoc;
440 //};
441 //class FilterScript;
442 
443 
444 struct MeshModelStateData
445 {
446 	int _mask;
447 	size_t _nvert;
448 	size_t _nface;
449 	size_t _nedge;
450 
MeshModelStateDataMeshModelStateData451 	MeshModelStateData(int mask, size_t nvert, size_t nface, size_t nedge)
452 		:_mask(mask), _nvert(nvert), _nface(nface), _nedge(nedge)
453 	{}
454 };
455 
456 class MeshDocumentStateData
457 {
458 public:
459 	MeshDocumentStateData();
460 	~MeshDocumentStateData();
461 
462 	void create(MeshDocument& md);
463 	QMap<int, MeshModelStateData>::iterator insert(const int key, const MeshModelStateData & value);
464 	QMap<int, MeshModelStateData>::iterator find(const int key);
465 	QMap<int, MeshModelStateData>::iterator begin();
466 	QMap<int, MeshModelStateData>::iterator end();
467 	void clear();
468 
469 private:
470 	mutable QReadWriteLock _lock;
471 	QMap<int, MeshModelStateData> _existingmeshesbeforeoperation;
472 };
473 
474 class MeshDocument : public QObject
475 {
476     Q_OBJECT
477 
478 public:
479 
480     MeshDocument();
481 
482     //deletes each meshModel
483     ~MeshDocument();
484 
485     /// returns the mesh with the given unique id
486     MeshModel *getMesh(int id);
487     MeshModel *getMesh(const QString& name);
488     MeshModel *getMeshByFullName(const QString& pathName);
489 
490 
491     //set the current mesh to be the one with the given ID
492     void setCurrentMesh( int new_curr_id );
493 
494     void setVisible(int meshId, bool val);
495 
496     /// returns the raster with the given unique id
497     RasterModel *getRaster(int i);
498 
499     //set the current raster to be the one with the given ID
500     void setCurrentRaster( int new_curr_id );
setCurrent(MeshModel * newCur)501     void setCurrent(MeshModel   *newCur)  { setCurrentMesh(newCur->id());}
setCurrent(RasterModel * newCur)502     void setCurrent(RasterModel *newCur)  { setCurrentRaster(newCur->id());}
503 
504     /// methods to access the set of Meshes in a ordered fashion.
505     MeshModel   *nextVisibleMesh(MeshModel *_m = NULL)
506     {
507       MeshModel *newM = nextMesh(_m);
508       if(newM==0)
509         return newM;
510 
511       if(newM->isVisible())
512         return newM;
513       else
514         return nextVisibleMesh(newM);
515     }
516 
517     MeshModel   *nextMesh(MeshModel *_m = NULL)
518     {
519       if(_m==0 && meshList.size()>0)
520         return meshList.at(0);
521       for (int i = 0; i < meshList.size(); ++i) {
522           if (meshList.at(i) == _m)
523           {
524             if(i+1 < meshList.size())
525               return meshList.at(i+1);
526           }
527       }
528       return 0;
529     }
530     /// methods to access the set of Meshes in a ordered fashion.
531     RasterModel   *nextRaster(RasterModel *_rm = NULL) {
532       for (int i = 0; i < rasterList.size(); ++i) {
533           if (rasterList.at(i) == _rm)
534           {
535             if(i+1 < rasterList.size())
536               return rasterList.at(i+1);
537           }
538       }
539       return 0;
540     }
541 
mm()542     MeshModel *mm() {
543         return currentMesh;
544     }
545 
546     //Could return 0 if no raster has been selected
rm()547     RasterModel *rm(){
548         return currentRaster;
549     }
550 
551     /// The very important member:
552     /// The list of MeshModels.
553     QList<MeshModel *> meshList;
554     /// The list of the raster models of the project
555     QList<RasterModel *> rasterList;
newMeshId()556     int newMeshId() {return meshIdCounter++;}
newRasterId()557     int newRasterId() {return rasterIdCounter++;}
558 
559     //functions to update the document entities (meshes and/or rasters) during the filters execution
560     //WARNING! please note that if you have to update both meshes and rasters calling updateRenderState function it's far more efficient
561     //than calling in sequence updateRenderRasterStateMeshes and updateRenderStateRasters. Use them only if you have to update only rasters or only meshes.
562     /*void updateRenderState(const QList<int>& mm,const int meshupdatemask,const QList<int>& rm,const int rasterupdatemask);
563 
564     void updateRenderStateMeshes(const QList<int>& mm,const int meshupdatemask);
565     void updateRenderStateRasters(const QList<int>& rm,const int rasterupdatemask);*/
566 	void requestUpdatingPerMeshDecorators(int mesh_id);
567 
568 private:
569     int meshIdCounter;
570     int rasterIdCounter;
571 
572     /**
573     All the files referred in a document are relative to the folder containing the project file.
574     this is the full path to the document.
575     */
576     QString fullPathFilename;
577 
578     //it is the label of the document. it should only be something like Project_n (a temporary name for a new empty document) or the fullPathFilename.
579     QString documentLabel;
580 
581 	MeshDocumentStateData mdstate;
582 public:
583 
meshDocStateData()584 	inline MeshDocumentStateData& meshDocStateData() { return mdstate; }
setDocLabel(const QString & docLb)585     void setDocLabel(const QString& docLb) {documentLabel = docLb;}
docLabel()586     QString docLabel() const {return documentLabel;}
pathName()587     QString pathName() const {QFileInfo fi(fullPathFilename); return fi.absolutePath();}
setFileName(const QString & newFileName)588     void setFileName(const QString& newFileName) {fullPathFilename = newFileName;}
589     GLLogStream Log;
590     FilterScript* filterHistory;
591     QStringList xmlhistory;
592 
size()593     int size() const {return meshList.size();}
isBusy()594     bool isBusy() { return busy;}    // used in processing. To disable access to the mesh by the rendering thread
setBusy(bool _busy)595     void setBusy(bool _busy)
596     {
597         /*if(busy && _busy==false)
598         {
599             emit meshDocumentModified();
600         }*/
601         busy=_busy;
602     }
603 
604 private:
605     bool  busy;
606 
607 public:
608     ///add a new mesh with the given name
609     MeshModel *addNewMesh(QString fullPath, QString Label, bool setAsCurrent=true);
610     MeshModel *addOrGetMesh(QString fullPath, const QString& Label, bool setAsCurrent=true);
611 
612 
613     ///remove the mesh from the list and delete it from memory
614     bool delMesh(MeshModel *mmToDel);
615 
616     ///add a new raster model
617     RasterModel *addNewRaster(/*QString rasterName*/);
618 
619     ///remove the raster from the list and delete it from memory
620     bool delRaster(RasterModel *rasterToDel);
621 
vn()622     int vn() /// Sum of all the vertices of all the meshes
623     {
624         int tot=0;
625         foreach(MeshModel *mmp, meshList)
626             tot+= mmp->cm.vn;
627         return tot;
628     }
fn()629     int fn() {
630         int tot=0;
631         foreach(MeshModel *mmp, meshList)
632             tot+= mmp->cm.fn;
633         return tot;
634     }
635 
bbox()636     Box3m bbox()
637     {
638 		Box3m FullBBox;
639 		foreach(MeshModel * mp, meshList)
640 			FullBBox.Add(mp->cm.Tr,mp->cm.bbox);
641 		return FullBBox;
642     }
643 
644     bool hasBeenModified();
645 
646 private:
647     MeshModel *currentMesh;
648     //the current raster model
649 	RasterModel* currentRaster;
650 
651 signals:
652     ///whenever the current mesh is changed (e.g. the user click on a different mesh)
653     // this signal will send out with the index of the newest mesh
654     void currentMeshChanged(int index);
655 
656     /// whenever the document (or even a single mesh) is modified by a filter
657     void meshDocumentModified();
658 
659     ///whenever the meshList is changed
660     void meshSetChanged();
661 
662 	void meshAdded(int index);
663     void meshRemoved(int index);
664 
665     ///whenever the rasterList is changed
666     void rasterSetChanged();
667 
668     //this signal is emitted when a filter request to update the mesh in the renderingState
669     void documentUpdated();
670 	void updateDecorators(int mesh_id);
671 
672 };// end class MeshDocument
673 
674 /*
675 A class designed to save partial aspects of the state of a mesh, such as vertex colors, current selections, vertex positions
676 and then be able to restore them later.
677 This is a fundamental part for the dynamic filters framework.
678 
679 Note: not all the MeshElements are supported!!
680 */
681 class MeshModelState
682 {
683 private:
684     int changeMask; // a bit mask indicating what have been changed. Composed of MeshModel::MeshElement (e.g. stuff like MeshModel::MM_VERTCOLOR)
685     MeshModel *m; // the mesh which the changes refers to.
686     std::vector<float> vertQuality;
687     std::vector<vcg::Color4b> vertColor;
688     std::vector<vcg::Color4b> faceColor;
689     std::vector<Point3m> vertCoord;
690     std::vector<Point3m> vertNormal;
691     std::vector<Point3m> faceNormal;
692     std::vector<bool> faceSelection;
693     std::vector<bool> vertSelection;
694     Matrix44m Tr;
695     Shotm shot;
696 public:
697     // This function save the <mask> portion of a mesh into the private members of the MeshModelState class;
698     void create(int _mask, MeshModel* _m);
699     bool apply(MeshModel *_m);
700     bool isValid(MeshModel *m);
maskChangedAtts()701     int maskChangedAtts() const {return changeMask;}
702 };
703 
704 
705 
706 #endif
707