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