1 /****************************************************************************
2 * MeshLab                                                           o o     *
3 * An extendible mesh processor                                    o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2005, 2006                                          \/)\/    *
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 
26 #include <common/interfaces.h>
27 #include <common/GLExtensionsManager.h>
28 
29 #include "glarea.h"
30 #include "mainwindow.h"
31 #include "multiViewer_Container.h"
32 #include "ml_default_decorators.h"
33 
34 #include <QFileDialog>
35 #include <QClipboard>
36 #include <QLocale>
37 #include <QPainterPath>
38 
39 #include <wrap/gl/picking.h>
40 #include <wrap/qt/trackball.h>
41 #include <wrap/qt/col_qt_convert.h>
42 #include <wrap/qt/shot_qt.h>
43 #include <wrap/qt/checkGLError.h>
44 #include <wrap/qt/gl_label.h>
45 #include <wrap/io_trimesh/export_ply.h>
46 #include <wrap/io_trimesh/import_ply.h>
47 #include<QOpenGLContext>
48 
49 
50 using namespace std;
51 using namespace vcg;
52 
GLArea(QWidget * parent,MultiViewer_Container * mvcont,RichParameterSet * current)53 GLArea::GLArea(QWidget *parent, MultiViewer_Container *mvcont, RichParameterSet *current)
54     : QGLWidget(parent,mvcont->sharedDataContext()),interrbutshow(false)
55 {
56 	makeCurrent();
57     parentmultiview = mvcont;
58     this->updateCustomSettingValues(*current);
59     animMode=AnimNone;
60     iRenderer=0; //Shader support
61     iEdit=0;
62     currentEditor=0;
63     suspendedEditor=false;
64     lastModelEdited = 0;
65     cfps=0;
66     lastTime=0;
67     hasToPick=false;
68     hasToSelectMesh=false;
69     hasToGetPickPos=false;
70     //hasToUpdateTexture=false;
71     helpVisible=false;
72     takeSnapTile=false;
73     activeDefaultTrackball=true;
74     infoAreaVisible = true;
75     trackBallVisible = true;
76     currentShader = NULL;
77     lastFilterRef = NULL;
78     //lastEditRef = NULL;
79     setAttribute(Qt::WA_DeleteOnClose,true);
80     fov = fovDefault();
81     clipRatioFar = 5;
82     clipRatioNear = clipRatioNearDefault();
83     nearPlane = .2f;
84     farPlane = 5.f;
85 
86     //if (mvcont != NULL)
87     //    shared = mvcont->sharedDataContext();
88 
89     id = mvcont->getNextViewerId();
90 
91     updateMeshSetVisibilities();
92     updateRasterSetVisibilities();
93     setAutoFillBackground(false);
94 
95     //Raster support
96     _isRaster =false;
97     opacity = 0.5;
98     zoom = false;
99     targetTex = 0;
100 
101     connect(this->md(), SIGNAL(currentMeshChanged(int)), this, SLOT(manageCurrentMeshChange()),Qt::QueuedConnection);
102     //connect(this->md(), SIGNAL(meshDocumentModified()), this, SLOT(updateAllPerMeshDecorators()),Qt::QueuedConnection);
103     connect(this->md(), SIGNAL(meshSetChanged()), this, SLOT(updateMeshSetVisibilities()));
104     connect(this->md(), SIGNAL(rasterSetChanged()), this, SLOT(updateRasterSetVisibilities()));
105     connect(this->md(), SIGNAL(documentUpdated()),this,SLOT(completeUpdateRequested()));
106 	connect(this->md(), SIGNAL(updateDecorators(int)),this,SLOT(updatePerMeshDecorators(int)));
107     connect(this, SIGNAL(updateLayerTable()), this->mw(), SIGNAL(updateLayerTable()));
108     connect(md(),SIGNAL(meshRemoved(int)),this,SLOT(meshRemoved(int)));
109 
110 	QShortcut *copyViewSC = new QShortcut(QKeySequence::Copy, (QWidget*)this);
111 	QObject::connect(copyViewSC, SIGNAL(activated()), (QWidget*)this, SLOT(copyToClip()));
112 	QShortcut *pasteViewSC = new QShortcut(QKeySequence::Paste, (QWidget*)this);
113 	QObject::connect(pasteViewSC, SIGNAL(activated()), (QWidget*)this, SLOT(pasteFromClip()));
114 
115     /*getting the meshlab MainWindow from parent, which is QWorkspace.
116     *note as soon as the GLArea is added as Window to the QWorkspace the parent of GLArea is a QWidget,
117     *which takes care about the window frame (its parent is the QWorkspace again).
118     */
119     MainWindow* mainwindow = this->mw();
120     //connecting the MainWindow Slots to GLArea signal (simple passthrough)
121     if(mainwindow != NULL){
122         connect(this,SIGNAL(updateMainWindowMenus()),mainwindow,SLOT(updateMenus()));
123         connect(mainwindow,SIGNAL(dispatchCustomSettings(RichParameterSet&)),this,SLOT(updateCustomSettingValues(RichParameterSet&)));
124     }else{
125         qDebug("The parent of the GLArea parent is not a pointer to the meshlab MainWindow.");
126     }
127 	lastloadedraster = -1;
128 }
129 
~GLArea()130 GLArea::~GLArea()
131 {
132 }
133 
134 /*
135 This member returns the information of the Mesh in terms of VC,VQ,FC,FQ,WT
136 where:
137 VC = VertColor,VQ = VertQuality,FC = FaceColor,FQ = FaceQuality,WT = WedgTexCoord
138 */
GetMeshInfoString()139 QString GLArea::GetMeshInfoString()
140 {
141     QString info;
142     if(mm()->hasDataMask(MeshModel::MM_VERTQUALITY) ) {info.append("VQ ");}
143     if(mm()->hasDataMask(MeshModel::MM_VERTCOLOR) )   {info.append("VC ");}
144     if(mm()->hasDataMask(MeshModel::MM_VERTRADIUS) )  {info.append("VR ");}
145     if(mm()->hasDataMask(MeshModel::MM_VERTTEXCOORD)) {info.append("VT ");}
146     if(mm()->hasDataMask(MeshModel::MM_VERTCURV) )    {info.append("VK ");}
147     if(mm()->hasDataMask(MeshModel::MM_VERTCURVDIR) ) {info.append("VD ");}
148     if(mm()->hasDataMask(MeshModel::MM_FACECOLOR) )   {info.append("FC ");}
149     if(mm()->hasDataMask(MeshModel::MM_FACEQUALITY) ) {info.append("FQ ");}
150     if(mm()->hasDataMask(MeshModel::MM_WEDGTEXCOORD)) {info.append("WT ");}
151     if(mm()->hasDataMask(MeshModel::MM_CAMERA) )      {info.append("MC ");}
152     if(mm()->hasDataMask(MeshModel::MM_POLYGONAL) )   {info.append("MP ");}
153 
154     return info;
155 }
156 
minimumSizeHint() const157 QSize GLArea::minimumSizeHint() const {return QSize(400,300);}
sizeHint() const158 QSize GLArea::sizeHint() const				{return QSize(400,300);}
159 
160 
initializeGL()161 void GLArea::initializeGL()
162 {
163 	makeCurrent();
164     glShadeModel(GL_SMOOTH);
165     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
166     glPixelStorei(GL_PACK_ALIGNMENT, 1);
167     glEnable(GL_DEPTH_TEST);
168     glEnable(GL_NORMALIZE);
169     static float diffuseColor[]={1.0,1.0,1.0,1.0};
170     glEnable(GL_LIGHT0);
171     glDisable(GL_LIGHT1);
172     glLightfv(GL_LIGHT1,GL_DIFFUSE,diffuseColor);
173     trackball.center=Point3f(0, 0, 0);
174     trackball.radius= 1;
175 
176     trackball_light.center=Point3f(0, 0, 0);
177     trackball_light.radius= 1;
178     GLExtensionsManager::initializeGLextensions();
179 	//doneCurrent();
180 }
181 
pasteTile()182 void GLArea::pasteTile()
183 {
184     QString outfile;
185 	makeCurrent();
186     glPushAttrib(GL_ENABLE_BIT);
187 	bool useAlfa = ss.background==1;
188 	QImage tileBuffer = grabFrameBuffer(useAlfa).mirrored(false, true);
189     if(ss.tiledSave)
190     {
191         outfile=QString("%1/%2_%3-%4.png")
192                 .arg(ss.outdir)
193                 .arg(ss.basename)
194                 .arg(tileCol,2,10,QChar('0'))
195                 .arg(tileRow,2,10,QChar('0'));
196         tileBuffer.mirrored(false,true).save(outfile,"PNG");
197     }
198     else
199     {
200         if (snapBuffer.isNull())
201             snapBuffer = QImage(tileBuffer.width() * ss.resolution, tileBuffer.height() * ss.resolution, tileBuffer.format());
202 
203         uchar *snapPtr = snapBuffer.bits() + (tileBuffer.bytesPerLine() * tileCol) + ((totalCols * tileRow) * tileBuffer.byteCount());
204         uchar *tilePtr = tileBuffer.bits();
205 
206         for (int y=0; y < tileBuffer.height(); y++)
207         {
208             memcpy((void*) snapPtr, (void*) tilePtr, tileBuffer.bytesPerLine());
209             snapPtr+=tileBuffer.bytesPerLine() * totalCols;
210             tilePtr+=tileBuffer.bytesPerLine();
211         }
212     }
213     tileCol++;
214 
215     if (tileCol >= totalCols)
216     {
217         tileCol=0;
218         tileRow++;
219 
220         if (tileRow >= totalRows)
221         {
222             if(ss.snapAllLayers)
223             {
224                 outfile=QString("%1/%2%3_L%4.png")
225                         .arg(ss.outdir).arg(ss.basename)
226                         .arg(ss.counter,2,10,QChar('0'))
227                         .arg(currSnapLayer,2,10,QChar('0'));
228             } else {
229                 outfile=QString("%1/%2%3.png")
230                         .arg(ss.outdir).arg(ss.basename)
231                         .arg(ss.counter++,2,10,QChar('0'));
232             }
233 
234             if(!ss.tiledSave)
235             {
236                 bool ret = (snapBuffer.mirrored(false,true)).save(outfile,"PNG");
237                 if (ret)
238                 {
239                     this->Logf(GLLogStream::SYSTEM, "Snapshot saved to %s",outfile.toLocal8Bit().constData());
240                     if(ss.addToRasters)
241                     {
242 						// get current transform, before is reset by the following importRaster
243 						Shotm shot_tmp = shotFromTrackball().first;
244 						float tmp_sca = trackball.track.sca;
245                         mw()->importRaster(outfile);
246 
247                         RasterModel *rastm = md()->rm();
248 						rastm->shot = shot_tmp;
249                         float ratio=(float)rastm->currentPlane->image.height()/(float)rastm->shot.Intrinsics.ViewportPx[1];
250                         rastm->shot.Intrinsics.ViewportPx[0]=rastm->currentPlane->image.width();
251                         rastm->shot.Intrinsics.ViewportPx[1]=rastm->currentPlane->image.height();
252                         rastm->shot.Intrinsics.PixelSizeMm[1]/=ratio;
253                         rastm->shot.Intrinsics.PixelSizeMm[0]/=ratio;
254                         rastm->shot.Intrinsics.CenterPx[0]= rastm->shot.Intrinsics.ViewportPx[0]/2.0;
255                         rastm->shot.Intrinsics.CenterPx[1]= rastm->shot.Intrinsics.ViewportPx[1]/2.0;
256 
257 						//importRaster has destroyed the original trackball state, now we restore it
258 						trackball.track.sca = tmp_sca;
259 						loadShot(QPair<Shotm, float>(shot_tmp, trackball.track.sca));
260                     }
261                 }
262                 else
263                 {
264                     Logf(GLLogStream::WARNING,"Error saving %s",outfile.toLocal8Bit().constData());
265                 }
266             }
267             takeSnapTile=false;
268             snapBuffer=QImage();
269         }
270     }
271     update();
272     glPopAttrib();
273 }
274 
275 
276 
drawGradient()277 void GLArea::drawGradient()
278 {
279 	makeCurrent();
280     glMatrixMode(GL_PROJECTION);
281     glPushMatrix();
282     glLoadIdentity();
283     glOrtho(-1,1,-1,1,-1,1);
284     glMatrixMode(GL_MODELVIEW);
285     glPushMatrix();
286     glLoadIdentity();
287     glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
288     glDisable(GL_DEPTH_TEST);
289     glDisable(GL_LIGHTING);
290     glDisable(GL_TEXTURE_2D);
291 
292 	if (!takeSnapTile)
293 	{
294 		glBegin(GL_TRIANGLE_STRIP);
295 		glColor(glas.backgroundTopColor);  glVertex2f(-1, 1);
296 		glColor(glas.backgroundBotColor);  glVertex2f(-1, -1);
297 		glColor(glas.backgroundTopColor);  glVertex2f(1, 1);
298 		glColor(glas.backgroundBotColor);  glVertex2f(1, -1);
299 		glEnd();
300 	}
301 	else
302 	{
303 		float xb = (-tileCol * 2) - 1;
304 		float yb = (-tileRow * 2) - 1;
305 		float xt = ((totalCols - tileCol) * 2) - 1;
306 		float yt = ((totalRows - tileRow) * 2) - 1;
307 
308 		glBegin(GL_TRIANGLE_STRIP);
309 		glColor(glas.backgroundTopColor);  glVertex2f(xb, yt);
310 		glColor(glas.backgroundBotColor);  glVertex2f(xb, yb);
311 		glColor(glas.backgroundTopColor);  glVertex2f(xt, yt);
312 		glColor(glas.backgroundBotColor);  glVertex2f(xt, yb);
313 		glEnd();
314 	}
315 
316     glPopAttrib();
317     glPopMatrix(); // restore modelview
318     glMatrixMode(GL_PROJECTION);
319     glPopMatrix();
320     glMatrixMode(GL_MODELVIEW);
321 	//doneCurrent();
322 }
323 
drawLight()324 void GLArea::drawLight()
325 {
326 	makeCurrent();
327     // ============== LIGHT TRACKBALL ==============
328     // Apply the trackball for the light direction
329     glPushMatrix();
330     trackball_light.GetView();
331     trackball_light.Apply();
332 
333     static float lightPosF[]={0.0,0.0,1.0,0.0};
334     glLightfv(GL_LIGHT0,GL_POSITION,lightPosF);
335     static float lightPosB[]={0.0,0.0,-1.0,0.0};
336     glLightfv(GL_LIGHT1,GL_POSITION,lightPosB);
337 
338     if (!(isDefaultTrackBall()))
339     {
340         glPushAttrib(GL_ENABLE_BIT | GL_CURRENT_BIT);
341         glColor3f(1,1,0);
342         glDisable(GL_LIGHTING);
343         const unsigned int lineNum=3;
344         glBegin(GL_LINES);
345         for(unsigned int i=0;i<=lineNum;++i)
346             for(unsigned int j=0;j<=lineNum;++j) {
347                 glVertex3f(-1.0f+i*2.0/lineNum,-1.0f+j*2.0/lineNum,-2);
348                 glVertex3f(-1.0f+i*2.0/lineNum,-1.0f+j*2.0/lineNum, 2);
349             }
350         glEnd();
351         glPopAttrib();
352     }
353     glPopMatrix();
354     if(!isDefaultTrackBall()) trackball_light.DrawPostApply();
355 
356 }
RenderForSelection(int pickX,int pickY)357 int GLArea::RenderForSelection(int pickX, int pickY)
358 {
359     makeCurrent();
360     if (mvc() == NULL)
361         return -1;
362 
363     MLSceneGLSharedDataContext* datacont = mvc()->sharedDataContext();
364     if (datacont == NULL)
365         return -1;
366 
367     int sz = int( md()->meshList.size())*5;
368     GLuint *selectBuf =new GLuint[sz];
369     glSelectBuffer(sz, selectBuf);
370     glRenderMode(GL_SELECT);
371     glInitNames();
372 
373     /* Because LoadName() won't work with no names on the stack */
374     glPushName(-1);
375     double mp[16];
376 
377     GLint viewport[4];
378     glGetIntegerv(GL_VIEWPORT,viewport);
379     glPushAttrib(GL_TRANSFORM_BIT);
380     glMatrixMode(GL_PROJECTION);
381     glGetDoublev(GL_PROJECTION_MATRIX ,mp);
382     glPushMatrix();
383     glLoadIdentity();
384     gluPickMatrix(pickX, pickY, 4, 4, viewport);
385     glMultMatrixd(mp);
386 
387     glMatrixMode(GL_MODELVIEW);
388     glPushMatrix();
389 
390     /*if (shared->highPrecisionRendering())
391         glTranslate(-shared->globalSceneCenter());*/
392 
393     foreach(MeshModel * mp, this->md()->meshList)
394     {
395         glLoadName(mp->id());
396 
397         datacont->setMeshTransformationMatrix(mp->id(), mp->cm.Tr);
398         datacont->draw(mp->id(), context());
399     }
400 
401     long hits;
402     glPopMatrix();
403     glMatrixMode(GL_PROJECTION);
404     glPopMatrix();
405     glMatrixMode(GL_MODELVIEW);
406     hits = glRenderMode(GL_RENDER);
407     glPopAttrib();
408 
409     std::vector< std::pair<double,unsigned int> > H;
410     for(long ii=0;ii<hits;ii++){
411         H.push_back( std::pair<double,unsigned int>(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3]));
412     }
413     std::sort(H.begin(),H.end());
414     delete [] selectBuf;
415     if(hits==0) return -1;
416     return H.front().second;
417 }
418 
paintEvent(QPaintEvent *)419 void GLArea::paintEvent(QPaintEvent* /*event*/)
420 {
421     if (mvc() == NULL)
422         return;
423     QPainter painter(this);
424     painter.beginNativePainting();
425 #ifdef Q_OS_MAC
426     glGetError();  // This seems required because on osx painter.beginNativePainting() trashes the err state of opengl
427 #endif
428 
429     makeCurrent();
430 
431     if(!isValid())
432         return;
433 
434     QElapsedTimer time;
435     time.start();
436 
437     /*if(!this->md()->isBusy())
438     {
439         initTexture(hasToUpdateTexture);
440         hasToUpdateTexture=false;
441     }*/
442 
443     ::glClearColor(1.0,1.0,1.0,0.0);
444     if (takeSnapTile && (ss.background == 3))
445         ::glClearColor(0.0, 0.0, 0.0, 0.0);
446     glEnable(GL_DEPTH_TEST);
447     glDepthMask(GL_TRUE);
448     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
449 
450     setView();  // Set Modelview and Projection matrix
451     if((!takeSnapTile) || (takeSnapTile && (ss.background==0)) )
452         drawGradient();  // draws the background
453 
454     drawLight();
455 
456     glPushMatrix();
457     // Finally apply the Trackball for the model
458     trackball.GetView();
459     trackball.Apply();
460 
461     glPushMatrix();
462 
463     if(!this->md()->isBusy())
464     {
465         glPushAttrib(GL_ALL_ATTRIB_BITS);
466 
467 
468         if ((iRenderer) && (parentmultiview != NULL))
469         {
470             MLSceneGLSharedDataContext* shared = parentmultiview->sharedDataContext();
471             if (shared != NULL)
472             {
473                 MLSceneGLSharedDataContext::PerMeshRenderingDataMap dt;
474                 shared->getRenderInfoPerMeshView(context(),dt);
475 
476                 iRenderer->Render(currentShader, *this->md(),dt,this);
477 
478                 MLDefaultMeshDecorators defdec(mw());
479 
480                 foreach(MeshModel * mp, this->md()->meshList)
481                 {
482                     if ((mp != NULL) && (meshVisibilityMap[mp->id()]))
483                     {
484                         QList<QAction *>& tmpset = iPerMeshDecoratorsListMap[mp->id()];
485                         for( QList<QAction *>::iterator it = tmpset.begin(); it != tmpset.end();++it)
486                         {
487                             MeshDecorateInterface * decorInterface = qobject_cast<MeshDecorateInterface *>((*it)->parent());
488                             decorInterface->decorateMesh(*it,*mp,this->glas.currentGlobalParamSet,this,&painter,md()->Log);
489                         }
490                         MLRenderingData meshdt;
491                         shared->getRenderInfoPerMeshView(mp->id(),context(),meshdt);
492                         defdec.decorateMesh(*mp,meshdt,&painter,md()->Log);
493                     }
494                 }
495             }
496         }
497         else
498         {
499             if(hasToSelectMesh) // right mouse click you have to select a mesh
500             {
501                 int newId=RenderForSelection(pointToPick[0],pointToPick[1]);
502                 if(newId>=0)
503                 {
504                     Logf(0,"Selected new Mesh %i",newId);
505                     md()->setCurrentMesh(newId);
506                     if (mw() != NULL)
507                         mw()->updateLayerDialog();
508                     //update();
509                 }
510                 hasToSelectMesh=false;
511             }
512             MLSceneGLSharedDataContext* datacont = mvc()->sharedDataContext();
513             if (datacont == NULL)
514                 return;
515 
516             foreach(MeshModel * mp, this->md()->meshList)
517             {
518                 if (meshVisibilityMap[mp->id()])
519                 {
520                     MLRenderingData curr;
521                     datacont->getRenderInfoPerMeshView(mp->id(),context(),curr);
522                     MLPerViewGLOptions opts;
523                     if (curr.get(opts) == false)
524                         throw MLException(QString("GLArea: invalid MLPerViewGLOptions"));
525                     setLightingColors(opts);
526 
527 
528                     if(opts._back_face_cull)
529                         glEnable(GL_CULL_FACE);
530                     else
531                         glDisable(GL_CULL_FACE);
532 
533                     datacont->setMeshTransformationMatrix(mp->id(),mp->cm.Tr);
534                     datacont->draw(mp->id(),context());
535                 }
536             }
537             foreach(MeshModel * mp, this->md()->meshList)
538             {
539                 if (meshVisibilityMap[mp->id()])
540                 {
541                     MLRenderingData curr;
542                     MLDefaultMeshDecorators defdec(mw());
543                     datacont->getRenderInfoPerMeshView(mp->id(), context(), curr);
544                     defdec.decorateMesh(*mp, curr, &painter, md()->Log);
545 
546                     QList<QAction *>& tmpset = iPerMeshDecoratorsListMap[mp->id()];
547                     for (QList<QAction *>::iterator it = tmpset.begin(); it != tmpset.end(); ++it)
548                     {
549                         MeshDecorateInterface * decorInterface = qobject_cast<MeshDecorateInterface *>((*it)->parent());
550                         decorInterface->decorateMesh(*it, *mp, this->glas.currentGlobalParamSet, this, &painter, md()->Log);
551                     }
552                 }
553             }
554         }
555         if (iEdit) {
556             iEdit->setLog(&md()->Log);
557             iEdit->Decorate(*mm(), this, &painter);
558         }
559 
560         glPopAttrib();
561     } ///end if busy
562 
563     glPopMatrix(); // We restore the state to immediately after the trackball (and before the bbox scaling/translating)
564 
565     if(trackBallVisible && !takeSnapTile && !(iEdit && !suspendedEditor))
566         trackball.DrawPostApply();
567 
568     foreach(QAction * p, iPerDocDecoratorlist)
569     {
570         MeshDecorateInterface * decorInterface = qobject_cast<MeshDecorateInterface *>(p->parent());
571         decorInterface->decorateDoc(p, *this->md(), this->glas.currentGlobalParamSet, this, &painter, md()->Log);
572     }
573 
574     // The picking of the surface position has to be done in object space,
575     // so after trackball transformation (and before the matrix associated to each mesh);
576     if(hasToPick && hasToGetPickPos)
577     {
578         Point3f pp;
579         hasToPick=false;
580         if(Pick<Point3f>(pointToPick[0],pointToPick[1],pp))
581         {
582             emit transmitSurfacePos(nameToGetPickPos, pp);
583             hasToGetPickPos=false;
584         }
585     }
586 
587     if (hasToPick && hasToGetPickCoords)
588     {
589         Point2f pp(pointToPick[0], pointToPick[1]);
590         hasToPick = false;
591         emit transmitPickedPos(nameToGetPickCoords, pp);
592         hasToGetPickCoords = false;
593     }
594 
595 
596 
597     // we want to write scene-space the point picked with double-click in the log
598     // we have to do it now, before leaving this transformation space
599     // we hook to the same mechanism double-click will be managed later on to move trackball
600     if(hasToPick && !hasToGetPickPos)
601     {
602         Point3f pp;
603         if(Pick<Point3f>(pointToPick[0],pointToPick[1],pp))
604         {
605             // write picked point in the log
606             Logf(0,"Recentering on point [%f %f %f] [%d,%d]",pp[0],pp[1],pp[2],pointToPick[0],pointToPick[1]);
607         }
608     }
609 
610     glPopMatrix(); // We restore the state to immediately before the trackball
611     //If it is a raster viewer draw the image as a texture
612     if (isRaster())
613     {
614         if ((md()->rm() != NULL) && (lastloadedraster != md()->rm()->id()))
615             loadRaster(md()->rm()->id());
616         drawTarget();
617     }
618 
619     // Double click move picked point to center
620     // It has to be done in the before trackball space (we MOVE the trackball itself...)
621     if(hasToPick && !hasToGetPickPos)
622     {
623         Point3f pp;
624         hasToPick=false;
625         if(Pick<Point3f>(pointToPick[0],pointToPick[1],pp))
626         {
627             trackball.MouseUp(pointToPick[0],pointToPick[1], vcg::Trackball::BUTTON_NONE );
628             trackball.Translate(-pp);
629             trackball.Scale(1.25f);
630 
631             QCursor::setPos(mapToGlobal(QPoint(width()/2+2,height()/2+2)));
632         }
633     }
634 
635     // ...and take a snapshot
636     if (takeSnapTile) pasteTile();
637 
638     // Finally display HELP if requested
639     if (isHelpVisible())
640         displayHelp();
641 
642     //Draw highlight if it is the current viewer
643     if(mvc()->currentId==id)
644         displayViewerHighlight();
645 
646     QString error = checkGLError::makeString("There are gl errors: ");
647     if(!error.isEmpty()) {
648         Log(GLLogStream::WARNING, qUtf8Printable(error));
649     }
650     //check if viewers are linked
651     MainWindow *window = qobject_cast<MainWindow *>(QApplication::activeWindow());
652     if(window && window->linkViewersAct->isChecked() && mvc()->currentId==id)
653         mvc()->updateTrackballInViewers();
654 
655     // Draw the log area background
656     // on the bottom of the glArea
657     if (infoAreaVisible)
658     {
659         glPushAttrib(GL_ENABLE_BIT);
660         glDisable(GL_DEPTH_TEST);
661         renderingFacilityString();
662         displayInfo(&painter);
663         displayRealTimeLog(&painter);
664         updateFps(time.elapsed());
665         glPopAttrib();
666     }
667     //doneCurrent();
668     glFlush();
669     glFinish();
670     painter.endNativePainting();
671 }
672 
displayMatrix(QPainter * painter,QRect areaRect)673 void GLArea::displayMatrix(QPainter *painter, QRect areaRect)
674 {
675 	makeCurrent();
676     painter->save();
677     qFont.setFamily("Helvetica");
678     qFont.setPixelSize(10);
679     qFont.setStyleStrategy(QFont::PreferAntialias);
680     painter->setFont(qFont);
681 
682     QString tableText;
683     for(int i=0;i<4;i++)
684         tableText+=QString("\t%1\t%2\t%3\t%4\n")
685                 .arg(mm()->cm.Tr[i][0],5,'f',2).arg(mm()->cm.Tr[i][1],5,'f',2)
686                 .arg(mm()->cm.Tr[i][2],5,'f',2).arg(mm()->cm.Tr[i][3],5,'f',2);
687 
688     QTextOption TO;
689     QTextOption::Tab ttt;
690     ttt.type=QTextOption::DelimiterTab;
691     ttt.delimiter = '.';
692     const int columnSpacing = 40;
693     ttt.position=columnSpacing;
694     QList<QTextOption::Tab> TabList;
695     for(int i=0;i<4;++i){
696         TabList.push_back(ttt);
697         ttt.position+=columnSpacing;
698     }
699     TO.setTabs(TabList);
700     painter->drawText(areaRect, tableText, TO);
701     painter->restore();
702 }
displayRealTimeLog(QPainter * painter)703 void GLArea::displayRealTimeLog(QPainter *painter)
704 {
705 	makeCurrent();
706     painter->endNativePainting();
707     painter->save();
708     painter->setPen(Qt::white);
709     Color4b logAreaColor = glas.logAreaColor;
710     glas.logAreaColor[3]=128;
711     if(mvc()->currentId!=id) logAreaColor /=2.0;
712 
713     qFont.setStyleStrategy(QFont::PreferAntialias);
714     qFont.setFamily("Helvetica");
715     qFont.setPixelSize(11);
716     painter->setFont(qFont);
717     float margin = qFont.pixelSize();
718     QFontMetrics metrics = QFontMetrics(font());
719     int border = qMax(4, metrics.leading());
720     qreal roundness = 10.0f;
721     QTextDocument doc;
722     doc.setDefaultFont(qFont);
723     int startingpoint = border;
724     //mQMultiMap<QString,std::pair<QString,QString> >::const_iterator it = md()->Log.RealTimeLogText.constBegin();it != md()->Log.RealTimeLogText.constEnd();++it)
725     for (QString keyIt : md()->Log.realTimeLogMultiMap().uniqueKeys() )
726     {
727         QList< QPair<QString,QString> > valueList = md()->Log.realTimeLogMultiMap().values(keyIt);
728         QPair<QString,QString> itVal;
729         // the map contains pairs of meshname, text
730         // the meshname is used only to disambiguate when there are more than two boxes with the same title
731         for(const QPair<QString,QString>& itVal: valueList)
732         {
733             QString HeadName = keyIt;
734             if(md()->Log.realTimeLogMultiMap().count(keyIt)>1)
735                 HeadName += " - "+itVal.first;
736             doc.clear();
737             doc.setDocumentMargin(margin*0.75);
738             QColor textColor = Qt::white;
739             QColor headColor(200,200,200);
740             doc.setHtml("<font color=\"" + headColor.name() + "\" size=\"+1\" ><p><i><b>" + HeadName + "</b></i></p></font>"
741                                                                                                        "<font color=\"" + textColor.name() + "\"             >" + itVal.second + "</font>");
742             QRect outrect(border,startingpoint,doc.size().width(),doc.size().height());
743             QPainterPath path;
744             painter->setBrush(QBrush(ColorConverter::ToQColor(logAreaColor),Qt::SolidPattern));
745             painter->setPen(ColorConverter::ToQColor(logAreaColor));
746             path.addRoundedRect(outrect,roundness,roundness);
747             painter->drawPath(path);
748             painter->save();
749             painter->translate(border,startingpoint);
750             doc.drawContents(painter);
751             painter->restore();
752             startingpoint = startingpoint + doc.size().height() + margin*.75;
753         }
754     }
755 
756     // After the rederaw we clear the RealTimeLog buffer!
757     md()->Log.clearRealTimeLog();
758     painter->restore();
759     painter->beginNativePainting();
760 }
761 
displayInfo(QPainter * painter)762 void GLArea::displayInfo(QPainter *painter)
763 {
764     makeCurrent();
765     if ((mvc() == NULL) || (md() == NULL))
766         return;
767     painter->endNativePainting();
768     painter->save();
769 
770     painter->setRenderHint(QPainter::HighQualityAntialiasing);
771     QPen textPen(QColor(255,255,255,200));
772     textPen.setWidthF(0.2f);
773     painter->setPen(textPen);
774 
775     qFont.setStyleStrategy(QFont::PreferAntialias);
776     qFont.setFamily("Helvetica");
777     qFont.setPixelSize(12);
778     painter->setFont(qFont);
779     QFontMetrics metrics = QFontMetrics(qFont);
780     int border = qMax(4, metrics.leading()) / 2;
781     int numLines = 6;
782 
783     float barHeight = ((metrics.height() + metrics.leading())*numLines) + 2 * border;
784 
785     QRect Column_0(width()/10, this->height()-barHeight+border, width()/2, this->height()-border);
786     QRect Column_1(width()/2 , this->height()-barHeight+border, width()*3/4,   this->height()-border);
787     QRect Column_2(width()*3/4 , this->height()-barHeight+border, width(),   this->height()-border);
788 
789     Color4b logAreaColor = glas.logAreaColor;
790     glas.logAreaColor[3]=128;
791     if(mvc()->currentId!=id) logAreaColor /=2.0;
792 
793     painter->fillRect(QRect(0, this->height()-barHeight, width(), this->height()), ColorConverter::ToQColor(logAreaColor));
794 
795     QString col1Text,col0Text;
796 
797     if(this->md()->size()>0)
798     {
799         if(this->md()->size()==1)
800         {
801             QLocale engLocale(QLocale::English, QLocale::UnitedStates);
802             col1Text += QString("Mesh: %1\n").arg(mm()->label());
803             col1Text += "Vertices: " + engLocale.toString(mm()->cm.vn) + " \n";
804             col1Text += "Faces: " + engLocale.toString(mm()->cm.fn) + " \n";
805         }
806         else
807         {
808             QLocale engLocale(QLocale::English, QLocale::UnitedStates);
809             QFileInfo inf = mm()->label();
810             col1Text += QString("Current Mesh: %1\n").arg(inf.completeBaseName());
811             col1Text += "Vertices: " + engLocale.toString(mm()->cm.vn) + "    (" + engLocale.toString(this->md()->vn()) + ") \n";
812             col1Text += "Faces: " + engLocale.toString(mm()->cm.fn) + "    (" + engLocale.toString(this->md()->fn()) + ") \n";
813         }
814 
815 
816         int svn = 0;
817         int sfn = 0;
818 
819         if (mm() != NULL)
820         {
821             svn = mm()->cm.svn;
822             sfn = mm()->cm.sfn;
823         }
824 
825         QLocale engLocale(QLocale::English, QLocale::UnitedStates);
826         col1Text += "Selection: v: " + engLocale.toString(svn) + " f: " + engLocale.toString(sfn) + " \n";
827 
828         col1Text += GetMeshInfoString();
829 
830         if(fov>5) col0Text += QString("FOV: %1\n").arg(fov);
831         else col0Text += QString("FOV: Ortho\n");
832         if ((cfps>0) && (cfps<1999))
833             col0Text += QString("FPS: %1\n").arg(cfps,7,'f',1);
834 
835         col0Text += renderfacility;
836 
837         if (clipRatioNear!=clipRatioNearDefault())
838             col0Text += QString("\nClipping Near:%1\n").arg(clipRatioNear,7,'f',2);
839         painter->drawText(Column_1, Qt::AlignLeft | Qt::TextWordWrap, col1Text);
840         painter->drawText(Column_0, Qt::AlignLeft | Qt::TextWordWrap, col0Text);
841         if(mm()->cm.Tr != Matrix44m::Identity() ) displayMatrix(painter, Column_2);
842     }
843     painter->restore();
844     painter->beginNativePainting();
845     //glPopAttrib();
846 }
847 
renderingFacilityString()848 void GLArea::renderingFacilityString()
849 {
850 
851 	renderfacility.clear();
852 	makeCurrent();
853 	if (md()->size() > 0)
854 	{
855 		enum RenderingType { FULL_BO, MIXED, FULL_IMMEDIATE_MODE };
856 		RenderingType rendtype = FULL_IMMEDIATE_MODE;
857 
858 		if (parentmultiview != NULL)
859 		{
860 			MLSceneGLSharedDataContext* shared = parentmultiview->sharedDataContext();
861 			if (shared != NULL)
862 			{
863 				int hh = 0;
864 				foreach(MeshModel* meshmod, md()->meshList)
865 				{
866 					if (shared->isBORenderingAvailable(meshmod->id()))
867 					{
868 						rendtype = MIXED;
869 						if ((rendtype == MIXED) && (hh == md()->meshList.size() - 1))
870 							rendtype = FULL_BO;
871 					}
872 					++hh;
873 				}
874 			}
875 		}
876 
877 		switch (rendtype)
878 		{
879 			case(FULL_BO):
880 			{
881 				renderfacility += QString("BO_RENDERING");
882 				break;
883 			}
884 			case(MIXED):
885 			{
886 				renderfacility += QString("MIXED_RENDERING");
887 				break;
888 			}
889 			case(FULL_IMMEDIATE_MODE):
890 			{
891 				renderfacility += QString("IMMEDIATE_MODE_RENDERING");
892 				break;
893 			}
894 		}
895 	}
896 }
897 
displayViewerHighlight()898 void GLArea::displayViewerHighlight()
899 {
900 	makeCurrent();
901     // Enter in 2D screen Mode again
902     glPushAttrib(GL_LINE_BIT);
903 
904     glMatrixMode(GL_PROJECTION);
905     glPushMatrix();
906     glLoadIdentity();
907     glOrtho(-1,1,-1,1,-1,1);
908     glMatrixMode(GL_MODELVIEW);
909     glPushMatrix();
910     glLoadIdentity();
911     glPushAttrib(GL_ENABLE_BIT);
912     glDisable(GL_DEPTH_TEST);
913     glDisable(GL_LIGHTING);
914     glDisable(GL_TEXTURE_2D);
915     glEnable(GL_BLEND);
916     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
917     glColor4f(1.0f,1.0f,1.0f,0.3f);
918     for(int width =5; width>0 ; width -= 2)
919     {
920         glLineWidth(width);
921         glBegin(GL_LINE_LOOP);
922         glVertex2f(-1.f,1.f);     glVertex2f( 1.f,1.f); glVertex2f( 1.f,-1.f);    glVertex2f(-1.f,-1.f);
923         glEnd();
924     }
925     // Closing 2D
926     glPopAttrib();
927     glPopMatrix(); // restore modelview
928     glMatrixMode(GL_PROJECTION);
929     glPopMatrix();
930     glMatrixMode(GL_MODELVIEW);
931     glPopAttrib();
932 
933 }
934 
935 
displayHelp()936 void GLArea::displayHelp()
937 {
938 	makeCurrent();
939     static QString tableText;
940     if(tableText.isEmpty())
941     {
942         QFile helpFile(":/images/onscreenHelp.txt");
943         if(helpFile.open(QFile::ReadOnly))
944             tableText=helpFile.readAll();
945         else assert(0);
946 #ifdef Q_OS_MAC
947         tableText.replace("Ctrl","Command");
948 #endif
949     }
950     md()->Log.RealTimeLog("Quick Help","",tableText);
951 }
952 
953 
saveSnapshot()954 void GLArea::saveSnapshot()
955 {
956 	makeCurrent();
957     // snap all layers
958     currSnapLayer=0;
959 
960     // number of subparts
961     totalCols=totalRows=ss.resolution;
962     tileRow=tileCol=0;
963 
964     if(ss.snapAllLayers)
965     {
966         while(currSnapLayer<this->md()->meshList.size())
967         {
968             tileRow=tileCol=0;
969             qDebug("Snapping layer %i",currSnapLayer);
970 			int mmit = 0;
971             foreach(MeshModel *mp,this->md()->meshList) {
972 				if (mmit == currSnapLayer)
973 					meshSetVisibility(mp, true);
974 				else
975 					meshSetVisibility(mp, false);
976 				mmit++;
977             }
978 
979             takeSnapTile=true;
980 			for (int tilenum = 0; tilenum < (ss.resolution*ss.resolution); tilenum++)
981 				repaint();
982             currSnapLayer++;
983         }
984 
985         //cleanup
986         foreach(MeshModel *mp,this->md()->meshList) {
987             meshSetVisibility(mp,true);
988         }
989         ss.counter++;
990     }
991     else
992     {
993         takeSnapTile=true;
994         update();
995     }
996 }
997 
998 // Slot called when the current mesh has changed.
manageCurrentMeshChange()999 void GLArea::manageCurrentMeshChange()
1000 {
1001     //if we have an edit tool open, notify it that the current layer has changed
1002     if(iEdit)
1003     {
1004         if(iEdit->isSingleMeshEdit())
1005             assert(lastModelEdited);  // if there is an editor that works on a single mesh
1006         // last model edited should always be set when start edit is called
1007 
1008         iEdit->LayerChanged(*this->md(), *lastModelEdited, this,parentmultiview->sharedDataContext());
1009 
1010         //now update the last model edited
1011         //TODO this is not the best design....   iEdit should maybe keep track of the model on its own
1012         lastModelEdited = this->md()->mm();
1013     }
1014     emit this->updateMainWindowMenus();
1015     // if the layer has changed update also the decoration.
1016     //	updateAllPerMeshDecorators();
1017 }
1018 
1019 ///// Execute a end/start pair for all the PerMesh decorator that are active in this glarea.
1020 ///// It is used when the document is changed or when some parameter changes
1021 ///// Note that it is rather inefficient. Such work should be done only once for each decorator.
1022 //void GLArea::updateAllPerMeshDecorators()
1023 //{
1024 //    MeshDocument* mdoc = md();
1025 //    if (mdoc == NULL)
1026 //        return;
1027 //	makeCurrent();
1028 //
1029 //    for (QMap<int, QList<QAction *> >::iterator i = iPerMeshDecoratorsListMap.begin(); i != iPerMeshDecoratorsListMap.end(); ++i )
1030 //    {
1031 //
1032 //        MeshModel *m = md()->getMesh(i.key());
1033 //        foreach(QAction *p , i.value())
1034 //        {
1035 //            MeshDecorateInterface * decorInterface = qobject_cast<MeshDecorateInterface *>(p->parent());
1036 //            decorInterface->endDecorate  (p, *m,this->glas.currentGlobalParamSet,this);
1037 //            decorInterface->setLog(&md()->Log);
1038 //            decorInterface->startDecorate(p,*m, this->glas.currentGlobalParamSet,this);
1039 //        }
1040 //    }
1041 //
1042 //    MultiViewer_Container* viewcont = mvc();
1043 //    if (viewcont == NULL)
1044 //        return;
1045 //
1046 //    MLSceneGLSharedDataContext* shared = viewcont->sharedDataContext();
1047 //    if (shared == NULL)
1048 //        return;
1049 //
1050 //    MLDefaultMeshDecorators defdec(mw());
1051 //    for(MeshModel* mm = mdoc->nextMesh();mm != NULL;mm = mdoc->nextMesh(mm))
1052 //    {
1053 //        MLRenderingData dt;
1054 //        shared->getRenderInfoPerMeshView(mm->id(),context(),dt);
1055 //        defdec.cleanMeshDecorationData(*mm,dt);
1056 //        defdec.initMeshDecorationData(*mm,dt);
1057 //    }
1058 //}
1059 
1060 
updateAllDecorators()1061 void GLArea::updateAllDecorators()
1062 {
1063 	updateAllPerMeshDecorators();
1064 	if (md() == NULL)
1065 		return;
1066 	foreach(QAction * p, iPerDocDecoratorlist)
1067 	{
1068 		MeshDecorateInterface * decorInterface = qobject_cast<MeshDecorateInterface *>(p->parent());
1069 		decorInterface->endDecorate(p, *md(), this->glas.currentGlobalParamSet, this);
1070 		decorInterface->setLog(&md()->Log);
1071 		decorInterface->startDecorate(p, *md(), this->glas.currentGlobalParamSet, this);
1072 	}
1073 	if (mvc() != NULL)
1074 		mvc()->updateAllViewers();
1075 }
1076 
setCurrentEditAction(QAction * editAction)1077 void GLArea::setCurrentEditAction(QAction *editAction)
1078 {
1079 	if ((parentmultiview == NULL) || (parentmultiview->sharedDataContext() == NULL))
1080 		return;
1081 
1082 	makeCurrent();
1083     assert(editAction);
1084     currentEditor = editAction;
1085 
1086     iEdit = actionToMeshEditMap.value(currentEditor);
1087 	if (iEdit == NULL)
1088 		return;
1089 
1090     lastModelEdited = this->md()->mm();
1091 
1092 	/*_oldvalues.clear();
1093 	parentmultiview->sharedDataContext()->getRenderInfoPerMeshView(context(), _oldvalues);*/
1094 
1095 	MLRenderingData dt;
1096 	if (iEdit->isSingleMeshEdit())
1097 	{
1098 		if (md()->mm() != NULL)
1099 		{
1100 			parentmultiview->sharedDataContext()->getRenderInfoPerMeshView(md()->mm()->id(), context(), dt);
1101 			iEdit->suggestedRenderingData(*(md()->mm()), dt);
1102 			MLPoliciesStandAloneFunctions::disableRedundatRenderingDataAccordingToPriorities(dt);
1103 			parentmultiview->sharedDataContext()->setRenderingDataPerMeshView(md()->mm()->id(), context(), dt);
1104 			parentmultiview->sharedDataContext()->manageBuffers(md()->mm()->id());
1105 		}
1106 	}
1107 	else
1108 	{
1109 		foreach(MeshModel* mm, md()->meshList)
1110 		{
1111 			if (mm != NULL)
1112 			{
1113 				parentmultiview->sharedDataContext()->getRenderInfoPerMeshView(mm->id(), context(), dt);
1114 				iEdit->suggestedRenderingData(*(mm), dt);
1115 				MLPoliciesStandAloneFunctions::disableRedundatRenderingDataAccordingToPriorities(dt);
1116 				parentmultiview->sharedDataContext()->setRenderingDataPerMeshView(mm->id(), context(), dt);
1117 				parentmultiview->sharedDataContext()->manageBuffers(mm->id());
1118 			}
1119 		}
1120 	}
1121 	if (mw() != NULL)
1122 		mw()->updateLayerDialog();
1123     if (!iEdit->StartEdit(*this->md(), this,parentmultiview->sharedDataContext()))
1124     {
1125         //iEdit->EndEdit(*(this->md()->mm()), this);
1126         endEdit();
1127     }
1128     else
1129     {
1130         Logf(GLLogStream::SYSTEM,"Started Mode %s", qUtf8Printable(currentEditor->text()));
1131 		if(mm()!=NULL)
1132             mm()->meshModified() = true;
1133         else assert(!iEdit->isSingleMeshEdit());
1134 		update();
1135     }
1136 }
1137 
1138 
readyToClose()1139 bool GLArea::readyToClose()
1140 {
1141 	makeCurrent();
1142     // Now do the actual closing of the glArea
1143 	if (getCurrentEditAction())
1144 	{
1145 		endEdit();
1146 		md()->meshDocStateData().clear();
1147 	}
1148     if (iRenderer)
1149         iRenderer->Finalize(currentShader, this->md(), this);
1150 
1151     // Now manage the closing of the decorator set;
1152     foreach(QAction* act, iPerDocDecoratorlist)
1153     {
1154         MeshDecorateInterface* mdec = qobject_cast<MeshDecorateInterface*>(act->parent());
1155         mdec->endDecorate(act,*md(),glas.currentGlobalParamSet,this);
1156         mdec->setLog(NULL);
1157     }
1158     iPerDocDecoratorlist.clear();
1159     QSet<QAction *> dectobeclose;
1160     for(QMap<int, QList<QAction *> >::iterator it = iPerMeshDecoratorsListMap.begin();it != iPerMeshDecoratorsListMap.end();++it)
1161     {
1162         foreach(QAction* curract,it.value())
1163             dectobeclose.insert(curract);
1164     }
1165 
1166     for(QSet<QAction *>::iterator it = dectobeclose.begin();it != dectobeclose.end();++it)
1167     {
1168         MeshDecorateInterface* mdec = qobject_cast<MeshDecorateInterface*>((*it)->parent());
1169         if (mdec != NULL)
1170         {
1171             mdec->endDecorate(*it,*md(),glas.currentGlobalParamSet,this);
1172             mdec->setLog(NULL);
1173         }
1174     }
1175     dectobeclose.clear();
1176     iPerMeshDecoratorsListMap.clear();
1177     if(targetTex) glDeleteTextures(1, &targetTex);
1178     emit glareaClosed();
1179     return true;
1180 }
1181 
keyReleaseEvent(QKeyEvent * e)1182 void GLArea::keyReleaseEvent ( QKeyEvent * e )
1183 {
1184 	makeCurrent();
1185     e->ignore();
1186     if(iEdit && !suspendedEditor)  iEdit->keyReleaseEvent(e,*mm(),this);
1187     else{
1188         if(e->key()==Qt::Key_Control) trackball.ButtonUp(QT2VCG(Qt::NoButton, Qt::ControlModifier ) );
1189         if(e->key()==Qt::Key_Shift) trackball.ButtonUp(QT2VCG(Qt::NoButton, Qt::ShiftModifier ) );
1190         if(e->key()==Qt::Key_Alt) trackball.ButtonUp(QT2VCG(Qt::NoButton, Qt::AltModifier ) );
1191     }
1192 }
1193 
keyPressEvent(QKeyEvent * e)1194 void GLArea::keyPressEvent ( QKeyEvent * e )
1195 {
1196 	makeCurrent();
1197     e->ignore();
1198     if(iEdit && !suspendedEditor)  iEdit->keyPressEvent(e,*mm(),this);
1199     else{
1200         if(e->key()==Qt::Key_Control) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::ControlModifier ) );
1201         if(e->key()==Qt::Key_Shift) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::ShiftModifier ) );
1202         if(e->key()==Qt::Key_Alt) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::AltModifier ) );
1203     }
1204 }
1205 
mousePressEvent(QMouseEvent * e)1206 void GLArea::mousePressEvent(QMouseEvent*e)
1207 {
1208 	makeCurrent();
1209     e->accept();
1210 	if (!this->hasFocus())
1211 	{
1212 		this->setFocus();
1213 	}
1214 
1215 	{
1216 		if ((iEdit != NULL) && !suspendedEditor)
1217 		{
1218 			iEdit->mousePressEvent(e, *mm(), this);
1219 		}
1220 		else
1221 		{
1222 			if (e->button() == Qt::RightButton) // Select a new current mesh
1223 			{
1224 				hasToSelectMesh = true;
1225 				this->pointToPick = Point2i(QT2VCG_X(this, e), QT2VCG_Y(this, e));
1226 			}
1227 			else
1228 			{
1229 				if ((e->modifiers() & Qt::ShiftModifier) &&
1230 					(e->modifiers() & Qt::ControlModifier) &&
1231 					(e->button() == Qt::LeftButton))
1232 					activeDefaultTrackball = false;
1233 				else activeDefaultTrackball = true;
1234 
1235 				if (isDefaultTrackBall())
1236 				{
1237 					if (QApplication::keyboardModifiers() & Qt::Key_Control) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::ControlModifier));
1238 					else trackball.ButtonUp(QT2VCG(Qt::NoButton, Qt::ControlModifier));
1239 					if (QApplication::keyboardModifiers() & Qt::Key_Shift) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::ShiftModifier));
1240 					else trackball.ButtonUp(QT2VCG(Qt::NoButton, Qt::ShiftModifier));
1241 					if (QApplication::keyboardModifiers() & Qt::Key_Alt) trackball.ButtonDown(QT2VCG(Qt::NoButton, Qt::AltModifier));
1242 					else trackball.ButtonUp(QT2VCG(Qt::NoButton, Qt::AltModifier));
1243 
1244 					trackball.MouseDown(QT2VCG_X(this, e), QT2VCG_Y(this, e), QT2VCG(e->button(), e->modifiers()));
1245 				}
1246 				else trackball_light.MouseDown(QT2VCG_X(this, e), QT2VCG_Y(this, e), QT2VCG(e->button(), Qt::NoModifier));
1247 			}
1248 		}
1249 	}
1250     update();
1251 }
1252 
mouseMoveEvent(QMouseEvent * e)1253 void GLArea::mouseMoveEvent(QMouseEvent*e)
1254 {
1255 	makeCurrent();
1256     if( (iEdit && !suspendedEditor) )
1257         iEdit->mouseMoveEvent(e,*mm(),this);
1258     else {
1259         if (isDefaultTrackBall())
1260         {
1261             trackball.MouseMove(QT2VCG_X(this,e), QT2VCG_Y(this,e));
1262             setCursorTrack(trackball.current_mode);
1263         }
1264         else trackball_light.MouseMove(QT2VCG_X(this,e), QT2VCG_Y(this,e));
1265     }
1266     update();
1267 }
1268 
1269 // When mouse is released we set the correct mouse cursor
mouseReleaseEvent(QMouseEvent * e)1270 void GLArea::mouseReleaseEvent(QMouseEvent*e)
1271 {
1272 	makeCurrent();
1273     //clearFocus();
1274     activeDefaultTrackball=true;
1275     if( (iEdit && !suspendedEditor) )
1276         iEdit->mouseReleaseEvent(e,*mm(),this);
1277     else {
1278         if (isDefaultTrackBall()) trackball.MouseUp(QT2VCG_X(this,e), QT2VCG_Y(this,e), QT2VCG(e->button(), e->modifiers() ) );
1279         else trackball_light.MouseUp(QT2VCG_X(this,e), QT2VCG_Y(this,e), QT2VCG(e->button(),e->modifiers()) );
1280         setCursorTrack(trackball.current_mode);
1281     }
1282 
1283     update();
1284 }
1285 
1286 //Processing of tablet events, interesting only for painting plugins
tabletEvent(QTabletEvent * e)1287 void GLArea::tabletEvent(QTabletEvent*e)
1288 {
1289 	makeCurrent();
1290     if(iEdit && !suspendedEditor) iEdit->tabletEvent(e,*mm(),this);
1291     else e->ignore();
1292 }
1293 
wheelEvent(QWheelEvent * e)1294 void GLArea::wheelEvent(QWheelEvent*e)
1295 {
1296 	makeCurrent();
1297     setFocus();
1298     if( (iEdit && !suspendedEditor) )
1299     {
1300         iEdit->wheelEvent(e,*mm(),this);
1301     }
1302     else
1303     {
1304         const int WHEEL_STEP = 120;
1305         float notch = e->delta()/ float(WHEEL_STEP);
1306         switch(e->modifiers())
1307         {
1308         case Qt::ControlModifier:
1309             {
1310                 clipRatioNear = math::Clamp(clipRatioNear*powf(1.1f, notch),0.01f,500.0f);
1311                 break;
1312             }
1313         case Qt::ShiftModifier:
1314             {
1315                 fov = math::Clamp(fov+1.2f*notch,5.0f,90.0f);
1316                 break;
1317             }
1318         case Qt::AltModifier:
1319             {
1320 				glas.pointSize = math::Clamp(glas.pointSize*powf(1.2f, notch), MLPerViewGLOptions::minPointSize(), MLPerViewGLOptions::maxPointSize());
1321                 MLSceneGLSharedDataContext* cont = mvc()->sharedDataContext();
1322                 if (cont != NULL)
1323                 {
1324 					foreach(MeshModel * mp, this->md()->meshList)
1325 					{
1326 						MLRenderingData dt;
1327 						cont->getRenderInfoPerMeshView(mp->id(), context(), dt);
1328 						MLPerViewGLOptions opt;
1329 						dt.get(opt);
1330 						opt._perpoint_pointsize = glas.pointSize;
1331 						opt._perpoint_pointsmooth_enabled = glas.pointSmooth;
1332 						opt._perpoint_pointattenuation_enabled = glas.pointDistanceAttenuation;
1333 						cont->setGLOptions(mp->id(), context(), opt);
1334 					}
1335 					if (mw() != NULL)
1336 						mw()->updateLayerDialog();
1337                 }
1338                 break;
1339             }
1340         default:
1341             {
1342                 if(isRaster())
1343                     this->opacity = math::Clamp( opacity*powf(1.2f, notch),0.1f,1.0f);
1344                 else
1345                     trackball.MouseWheel( e->delta()/ float(WHEEL_STEP));
1346                 break;
1347             }
1348         }
1349     }
1350     update();
1351 }
1352 
1353 
mouseDoubleClickEvent(QMouseEvent * e)1354 void GLArea::mouseDoubleClickEvent ( QMouseEvent * e )
1355 {
1356 	makeCurrent();
1357 	if ((iEdit == NULL) || suspendedEditor)
1358 	{
1359 		hasToPick = true;
1360 		pointToPick = Point2i(QT2VCG_X(this, e), QT2VCG_Y(this, e));
1361 	}
1362     update();
1363 }
1364 
focusInEvent(QFocusEvent * e)1365 void GLArea::focusInEvent ( QFocusEvent * e )
1366 {
1367 	makeCurrent();
1368     QWidget::focusInEvent(e);
1369     emit currentViewerChanged(id);
1370 }
1371 
setCursorTrack(vcg::TrackMode * tm)1372 void GLArea::setCursorTrack(vcg::TrackMode *tm)
1373 {
1374 	makeCurrent();
1375     //static QMap<QString,QCursor> curMap;
1376     if(curMap.isEmpty())
1377     {
1378         curMap[QString("")]=QCursor(Qt::ArrowCursor);
1379         curMap["SphereMode"]=QCursor(QPixmap(":/images/cursors/plain_trackball.png"),1,1);
1380         curMap["PanMode"]=QCursor(QPixmap(":/images/cursors/plain_pan.png"),1,1);
1381         curMap["ScaleMode"]=QCursor(QPixmap(":/images/cursors/plain_zoom.png"),1,1);
1382         curMap["PickMode"]=QCursor(QPixmap(":/images/cursors/plain_pick.png"),1,1);
1383     }
1384     if(tm) setCursor(curMap[tm->Name()]);
1385     else
1386         if(hasToGetPickPos) setCursor(curMap["PickMode"]);
1387         else setCursor(curMap[""]);
1388 
1389 }
1390 
setDecorator(QString name,bool state)1391 void GLArea::setDecorator(QString name, bool state)
1392 {
1393 	makeCurrent();
1394     updateDecorator(name, false, state);
1395 }
1396 
toggleDecorator(QString name)1397 void GLArea::toggleDecorator(QString name)
1398 {
1399 	makeCurrent();
1400     updateDecorator(name, true, false);
1401 }
1402 
1403 
updateDecorator(QString name,bool toggle,bool stateToSet)1404 void GLArea::updateDecorator(QString name, bool toggle, bool stateToSet)
1405 {
1406 	makeCurrent();
1407     MeshDecorateInterface *iDecorateTemp = this->mw()->PM.getDecoratorInterfaceByName(name);
1408     if (!iDecorateTemp) {
1409         this->Logf(GLLogStream::SYSTEM,"Could not get Decorate interface %s", qUtf8Printable(name));
1410         this->Log(GLLogStream::SYSTEM,"Known decorate interfaces:");
1411         for (auto tt : this->mw()->PM.meshDecoratePlugins()) {
1412             for (auto action : tt->actions()) {
1413                 this->Logf(GLLogStream::SYSTEM,"- %s", qUtf8Printable(tt->decorationName(action)));
1414             }
1415         }
1416         return;
1417     }
1418     QAction *action = iDecorateTemp->action(name);
1419 
1420     if(iDecorateTemp->getDecorationClass(action)== MeshDecorateInterface::PerDocument)
1421     {
1422         bool found=this->iPerDocDecoratorlist.removeOne(action);
1423         if(found)
1424         {
1425             if(toggle || stateToSet==false){
1426                 iDecorateTemp->endDecorate(action,*md(),glas.currentGlobalParamSet,this);
1427                 iDecorateTemp->setLog(NULL);
1428                 this->Logf(GLLogStream::SYSTEM,"Disabled Decorate mode %s", qUtf8Printable(action->text()));
1429             } else
1430                 this->Logf(GLLogStream::SYSTEM,"Trying to disable an already disabled Decorate mode %s", qUtf8Printable(action->text()));
1431         }
1432         else{
1433             if(toggle || stateToSet==true){
1434                 iDecorateTemp->setLog(&(this->md()->Log));
1435                 bool ret = iDecorateTemp->startDecorate(action,*md(), glas.currentGlobalParamSet, this);
1436                 if(ret) {
1437                     this->iPerDocDecoratorlist.push_back(action);
1438                     this->Logf(GLLogStream::SYSTEM,"Enabled Decorate mode %s", qUtf8Printable(action->text()));
1439                 }
1440                 else this->Logf(GLLogStream::SYSTEM,"Failed start of Decorate mode %s", qUtf8Printable(action->text()));
1441             } else
1442                 this->Logf(GLLogStream::SYSTEM,"Trying to enable an already enabled Decorate mode %s", qUtf8Printable(action->text()));
1443         }
1444     }
1445 
1446     if(iDecorateTemp->getDecorationClass(action)== MeshDecorateInterface::PerMesh)
1447     {
1448         MeshModel &currentMeshModel = *mm();
1449         bool found=this->iCurPerMeshDecoratorList().removeOne(action);
1450         if(found)
1451         {
1452             if(toggle || stateToSet==false){
1453                 iDecorateTemp->endDecorate(action,currentMeshModel,glas.currentGlobalParamSet,this);
1454                 iDecorateTemp->setLog(NULL);
1455                 this->Logf(0,"Disabled Decorate mode %s", qUtf8Printable(action->text()));
1456             } else
1457                 this->Logf(GLLogStream::SYSTEM,"Trying to disable an already disabled Decorate mode %s", qUtf8Printable(action->text()));
1458         }
1459         else{
1460             if(toggle || stateToSet==true){
1461                 QString errorMessage;
1462                 if (iDecorateTemp->isDecorationApplicable(action,currentMeshModel,errorMessage))
1463                 {
1464                     iDecorateTemp->setLog(&md()->Log);
1465                     bool ret = iDecorateTemp->startDecorate(action,currentMeshModel, glas.currentGlobalParamSet, this);
1466                     if(ret) {
1467                         this->iCurPerMeshDecoratorList().push_back(action);
1468                         this->Logf(GLLogStream::SYSTEM,"Enabled Decorate mode %s", qUtf8Printable(action->text()));
1469                     }
1470                     else this->Logf(GLLogStream::SYSTEM,"Failed Decorate mode %s", qUtf8Printable(action->text()));
1471                 } else
1472                     this->Logf(GLLogStream::SYSTEM,"Error in Decorate mode %s: %s", qUtf8Printable(action->text()), qUtf8Printable(errorMessage));
1473 
1474             }
1475         }
1476     }
1477 }
1478 
1479 //void GLArea::setDrawMode(vcg::GLW::DrawMode mode)
1480 //{
1481 //	makeCurrent();
1482 //	for(QMap<int,RenderMode>::iterator it = rendermodemap.begin();it != rendermodemap.end();++it)
1483 //		it.value().drawMode = mode;
1484 //	update();
1485 //}
1486 //
1487 //void GLArea::setDrawMode(RenderMode& rm,vcg::GLW::DrawMode mode )
1488 //{
1489 //	makeCurrent();
1490 //    rm.drawMode = mode;
1491 //    update();
1492 //}
1493 //
1494 //void GLArea::setColorMode(vcg::GLW::ColorMode mode)
1495 //{
1496 //	makeCurrent();
1497 //    for(QMap<int,RenderMode>::iterator it = rendermodemap.begin();it != rendermodemap.end();++it)
1498 //        it.value().colorMode = mode;
1499 //    update();
1500 //}
1501 //
1502 //void GLArea::setColorMode( RenderMode& rm,vcg::GLW::ColorMode mode )
1503 //{
1504 //	makeCurrent();
1505 //    rm.colorMode = mode;
1506 //    update();
1507 //}
1508 //
1509 //void GLArea::setTextureMode(vcg::GLW::TextureMode mode)
1510 //{
1511 //	makeCurrent();
1512 //    for(QMap<int,RenderMode>::iterator it = rendermodemap.begin();it != rendermodemap.end();++it)
1513 //        it.value().textureMode = mode;
1514 //    update();
1515 //}
1516 //
1517 //void GLArea::setTextureMode(RenderMode& rm,vcg::GLW::TextureMode mode)
1518 //{
1519 //	makeCurrent();
1520 //    rm.textureMode = mode;
1521 //    update();
1522 //}
1523 //
1524 //void GLArea::setLight(bool setState)
1525 //{
1526 //	makeCurrent();
1527 //    for(QMap<int,RenderMode>::iterator it = rendermodemap.begin();it != rendermodemap.end();++it)
1528 //        it.value().lighting = setState;
1529 //    update();
1530 //}
1531 //
1532 //void GLArea::setLightMode(bool state,LightingModel lmode)
1533 //{
1534 //	makeCurrent();
1535 //    for(QMap<int,RenderMode>::iterator it = rendermodemap.begin();it != rendermodemap.end();++it)
1536 //    {
1537 //        switch(lmode)
1538 //        {
1539 //        case LDOUBLE:		it.value().doubleSideLighting = state;	break;
1540 //        case LFANCY:		it.value().fancyLighting = state; break;
1541 //        }
1542 //    }
1543 //    update();
1544 //}
1545 //
1546 //void GLArea::setBackFaceCulling(bool enabled)
1547 //{
1548 //	makeCurrent();
1549 //    for(QMap<int,RenderMode>::iterator it = rendermodemap.begin();it != rendermodemap.end();++it)
1550 //        it.value().backFaceCull = enabled;
1551 //    update();
1552 //}
1553 //
setLightingColors(const MLPerViewGLOptions & opts)1554 void GLArea::setLightingColors(const MLPerViewGLOptions& opts)
1555 {
1556     makeCurrent();
1557     if (opts._double_side_lighting || opts._fancy_lighting)
1558         glEnable(GL_LIGHT1);
1559     else
1560         glDisable(GL_LIGHT1);
1561 
1562 	//WARNING!!!!! ALL THIS DATA SHOULD BE MOVED INSIDE THE OPTS....IN THE NEXT MESHLAB RELEASE....MAYBE.....
1563     glLightfv(GL_LIGHT0, GL_AMBIENT, Color4f::Construct(glas.baseLightAmbientColor).V());
1564     glLightfv(GL_LIGHT0, GL_DIFFUSE, Color4f::Construct(glas.baseLightDiffuseColor).V());
1565     glLightfv(GL_LIGHT0, GL_SPECULAR,Color4f::Construct(glas.baseLightSpecularColor).V());
1566 
1567     glLightfv(GL_LIGHT1, GL_AMBIENT, Color4f::Construct(glas.baseLightAmbientColor).V());
1568     glLightfv(GL_LIGHT1, GL_DIFFUSE, Color4f::Construct(glas.baseLightDiffuseColor).V());
1569     glLightfv(GL_LIGHT1, GL_SPECULAR,Color4f::Construct(glas.baseLightSpecularColor).V());
1570     if(opts._fancy_lighting)
1571     {
1572         glLightfv(GL_LIGHT0, GL_DIFFUSE, Color4f::Construct(glas.fancyFLightDiffuseColor).V());
1573         glLightfv(GL_LIGHT1, GL_DIFFUSE, Color4f::Construct(glas.fancyBLightDiffuseColor).V());
1574     }
1575 	//*********************************************************************************************************
1576 }
1577 
setView()1578 void GLArea::setView()
1579 {
1580 	makeCurrent();
1581     glViewport(0,0, (GLsizei) QTLogicalToDevice(this,width()),(GLsizei) QTLogicalToDevice(this,height()));
1582 
1583     GLfloat fAspect = (GLfloat)width()/height();
1584     glMatrixMode(GL_PROJECTION);
1585     glLoadIdentity();
1586     Matrix44f mtTr; mtTr.SetTranslate( trackball.center);
1587     Matrix44f mtSc; mtSc.SetScale(4.0f,4.0f,4.0f);
1588     Matrix44f mt = mtSc * mtTr * trackball.Matrix() *(-mtTr);
1589     //    Matrix44f mt =  trackball.Matrix();
1590 
1591     Box3m bb;
1592     bb.Add(Matrix44m::Construct(mt),this->md()->bbox());
1593     float cameraDist = this->getCameraDistance();
1594 
1595     if(fov<=5) cameraDist = 8.0f; // small hack for orthographic projection where camera distance is rather meaningless...
1596 
1597     nearPlane = cameraDist*clipRatioNear;
1598     farPlane = cameraDist + max(viewRatio(),float(-bb.min[2]));
1599 
1600     //    qDebug("tbcenter %f %f %f",trackball.center[0],trackball.center[1],trackball.center[2]);
1601     //    qDebug("camera dist %f far  %f",cameraDist, farPlane);
1602     //    qDebug("Bb %f %f %f - %f %f %f", bb.min[0], bb.min[1], bb.min[2], bb.max[0], bb.max[1], bb.max[2]);
1603 
1604     if (!takeSnapTile)
1605     {
1606         if(fov==5)	glOrtho( -viewRatio()*fAspect, viewRatio()*fAspect, -viewRatio(), viewRatio(),  nearPlane, farPlane);
1607         else		gluPerspective(fov, fAspect, nearPlane, farPlane);
1608     }
1609     else	setTiledView(fov, viewRatio(), fAspect, nearPlane, farPlane, cameraDist);
1610 
1611     glMatrixMode(GL_MODELVIEW);
1612     glLoadIdentity();
1613     gluLookAt(0, 0, cameraDist, 0, 0, 0, 0, 1, 0);
1614 }
1615 
setTiledView(GLdouble fovY,float viewRatio,float fAspect,GLdouble zNear,GLdouble zFar,float)1616 void GLArea::setTiledView(GLdouble fovY, float viewRatio, float fAspect, GLdouble zNear, GLdouble zFar,  float /*cameraDist*/)
1617 {
1618 	makeCurrent();
1619     if(fovY<=5)
1620     {
1621         GLdouble fLeft   = -viewRatio*fAspect;
1622         GLdouble fRight  =  viewRatio*fAspect;
1623         GLdouble fBottom = -viewRatio;
1624         GLdouble fTop    =  viewRatio;
1625 
1626         GLdouble tDimX = fabs(fRight-fLeft) / totalCols;
1627         GLdouble tDimY = fabs(fTop-fBottom) / totalRows;
1628 
1629 
1630         glOrtho(fLeft   + tDimX * tileCol, fLeft   + tDimX * (tileCol+1),     /* left, right */
1631                 fBottom + tDimY * tileRow, fBottom + tDimY * (tileRow+1),     /* bottom, top */
1632                 zNear, zFar);
1633     }
1634     else
1635     {
1636         GLdouble fTop    = zNear * tan(math::ToRad(fovY/2.0));
1637         GLdouble fRight  = fTop * fAspect;
1638         GLdouble fBottom = -fTop;
1639         GLdouble fLeft   = -fRight;
1640 
1641         // tile Dimension
1642         GLdouble tDimX = fabs(fRight-fLeft) / totalCols;
1643         GLdouble tDimY = fabs(fTop-fBottom) / totalRows;
1644 
1645         glFrustum(fLeft   + tDimX * tileCol, fLeft   + tDimX * (tileCol+1),
1646                   fBottom + tDimY * tileRow, fBottom + tDimY * (tileRow+1), zNear, zFar);
1647     }
1648 }
1649 
updateFps(float deltaTime)1650 void GLArea::updateFps(float deltaTime)
1651 {
1652     const int avgSize =10;
1653     static float fpsVector[avgSize];
1654     static int j=0;
1655     float averageFps=0;
1656     if (deltaTime>0) {
1657         fpsVector[j]=deltaTime;
1658         j=(j+1) % avgSize;
1659     }
1660     for (int i=0;i<avgSize;i++) averageFps+=fpsVector[i];
1661     cfps=1000.0f/(averageFps/avgSize);
1662     lastTime=deltaTime;
1663 }
1664 
resetTrackBall()1665 void GLArea::resetTrackBall()
1666 {
1667     makeCurrent();
1668     trackball.Reset();
1669     float newScale= 3.0f/this->md()->bbox().Diag();
1670     trackball.track.sca = newScale;
1671     trackball.track.tra.Import(-this->md()->bbox().Center());
1672     clipRatioNear = clipRatioNearDefault();
1673     if (!isRaster())
1674         fov=fovDefault();
1675     update();
1676 }
1677 
hideEvent(QHideEvent *)1678 void GLArea::hideEvent(QHideEvent * /*event*/)
1679 {
1680     trackball.current_button=0;
1681 }
1682 
sendViewPos(QString name)1683 void GLArea::sendViewPos(QString name)
1684 {
1685 #ifndef VCG_USE_EIGEN
1686     Point3f pos=  trackball.track.InverseMatrix() *Inverse(trackball.camera.model) *Point3f(0,0,0);
1687 #else
1688     Point3f pos=  Eigen::Transform3f(trackball.track.InverseMatrix()) * Eigen::Transform3f(Inverse(trackball.camera.model)).translation();
1689 #endif
1690     emit transmitViewPos(name, pos);
1691 }
1692 
sendSurfacePos(QString name)1693 void GLArea::sendSurfacePos(QString name)
1694 {
1695     qDebug("sendSurfacePos %s", qUtf8Printable(name));
1696     nameToGetPickPos = name;
1697     hasToGetPickPos=true;
1698 }
1699 
sendPickedPos(QString name)1700 void GLArea::sendPickedPos(QString name)
1701 {
1702 	qDebug("sendPickedPos %s", qUtf8Printable(name));
1703 	nameToGetPickCoords = name;
1704 	hasToGetPickCoords = true;
1705 }
1706 
sendViewDir(QString name)1707 void GLArea::sendViewDir(QString name)
1708 {
1709     Point3f dir= getViewDir();
1710     emit transmitViewDir(name,dir);
1711 }
1712 
sendMeshShot(QString name)1713 void GLArea::sendMeshShot(QString name)
1714 {
1715     Shotm curShot=this->md()->mm()->cm.shot;
1716     emit transmitShot(name, curShot);
1717 }
1718 
sendMeshMatrix(QString name)1719 void GLArea::sendMeshMatrix(QString name)
1720 {
1721     Matrix44m mat=this->md()->mm()->cm.Tr;
1722     emit transmitMatrix(name, mat);
1723 }
1724 
sendViewerShot(QString name)1725 void GLArea::sendViewerShot(QString name)
1726 {
1727     Shotm curShot=shotFromTrackball().first;
1728     emit transmitShot(name, curShot);
1729 }
sendRasterShot(QString name)1730 void GLArea::sendRasterShot(QString name)
1731 {
1732     Shotm curShot;
1733     if (this->md()->rm() != NULL)
1734         curShot = this->md()->rm()->shot;
1735     emit transmitShot(name, curShot);
1736 }
1737 
sendCameraPos(QString name)1738 void GLArea::sendCameraPos( QString name )
1739 {
1740 	Point3f pos = trackball.camera.ViewPoint();
1741 	emit transmitCameraPos(name, pos);
1742 }
1743 
sendTrackballPos(QString name)1744 void GLArea::sendTrackballPos(QString name)
1745 {
1746 	Point3f pos = -trackball.track.tra;
1747 	emit transmitTrackballPos(name, pos);
1748 }
1749 
getViewDir()1750 Point3f GLArea::getViewDir()
1751 {
1752     vcg::Matrix44f rotM;
1753     trackball.track.rot.ToMatrix(rotM);
1754     return vcg::Inverse(rotM)*vcg::Point3f(0,0,1);
1755 }
1756 
updateCustomSettingValues(RichParameterSet & rps)1757 void GLArea::updateCustomSettingValues( RichParameterSet& rps )
1758 {
1759 	makeCurrent();
1760     glas.updateGlobalParameterSet(rps);
1761 
1762     this->update();
1763 }
1764 
initGlobalParameterSet(RichParameterSet * defaultGlobalParamSet)1765 void GLArea::initGlobalParameterSet( RichParameterSet * defaultGlobalParamSet)
1766 {
1767     GLAreaSetting::initGlobalParameterSet(defaultGlobalParamSet);
1768 }
1769 
1770 //Don't alter the state of the other elements in the visibility map
updateMeshSetVisibilities()1771 void GLArea::updateMeshSetVisibilities()
1772 {
1773     meshVisibilityMap.clear();
1774     foreach(MeshModel * mp, this->md()->meshList)
1775     {
1776         //Insert the new pair in the map; If the key is already in the map, its value will be overwritten
1777         meshVisibilityMap.insert(mp->id(),mp->visible);
1778     }
1779 }
1780 
1781 //Don't alter the state of the other elements in the visibility map
updateRasterSetVisibilities()1782 void GLArea::updateRasterSetVisibilities()
1783 {
1784     //Align rasterVisibilityMap state with rasterList state
1785     //Deleting from the map the visibility of the deleted rasters
1786     QMapIterator<int, bool> i(rasterVisibilityMap);
1787     while (i.hasNext()) {
1788         i.next();
1789         bool found =false;
1790         foreach(RasterModel * rp, this->md()->rasterList)
1791         {
1792             if(rp->id() == i.key())
1793             {
1794                 found = true;
1795                 break;
1796             }
1797         }
1798         if(!found)
1799             rasterVisibilityMap.remove(i.key());
1800     }
1801 
1802     foreach(RasterModel * rp, this->md()->rasterList)
1803     {
1804         //Insert the new pair in the map;If the key is already in the map, its value will be overwritten
1805         rasterVisibilityMap.insert(rp->id(),rp->visible);
1806     }
1807 }
1808 
meshSetVisibility(MeshModel * mp,bool visibility)1809 void GLArea::meshSetVisibility(MeshModel *mp, bool visibility)
1810 {
1811     mp->visible=visibility;
1812     meshVisibilityMap[mp->id()]=visibility;
1813 }
1814 
addRasterSetVisibility(int rasterId,bool visibility)1815 void GLArea::addRasterSetVisibility(int rasterId, bool visibility)
1816 {
1817     rasterVisibilityMap.insert(rasterId,visibility);
1818 }
1819 
1820 //void GLArea::getPerDocGlobalRenderingData(MLRenderingData& dt) const
1821 //{
1822 //	dt = _perdocglobaldt;
1823 //}
1824 //
1825 //void GLArea::setPerDocGlobalRenderingData(const MLRenderingData& dt)
1826 //{
1827 //	_perdocglobaldt = dt;
1828 //}
1829 
1830 // --------------- Raster view -------------------------------------
setIsRaster(bool viewMode)1831 void GLArea::setIsRaster(bool viewMode){
1832     _isRaster= viewMode;
1833 }
1834 
1835 // this slot is called when someone press the showraster button on the toolbar
showRaster(bool resetViewFlag)1836 void GLArea::showRaster(bool resetViewFlag)
1837 {
1838 	makeCurrent();
1839     if(!this->isRaster())
1840     {
1841         lastViewBeforeRasterMode = this->viewToText();
1842         setIsRaster(true);
1843         loadRaster(md()->rm()->id() );
1844     } else
1845     {
1846         this->setIsRaster(false);
1847         QDomDocument doc("StringDoc");
1848         doc.setContent(lastViewBeforeRasterMode);
1849         if(resetViewFlag) this->loadViewFromViewStateFile(doc);
1850         else this->update();
1851     }
1852 }
1853 
loadRaster(int id)1854 void GLArea::loadRaster(int id)
1855 {
1856 	lastloadedraster = id;
1857     foreach(RasterModel *rm, this->md()->rasterList)
1858         if(rm->id()==id)
1859         {
1860             this->md()->setCurrentRaster(id);
1861             if (rm->currentPlane->image.isNull())
1862             {
1863                 Logf(0,"Image file %s has not been correctly loaded, a fake image is going to be shown.",rm->currentPlane->fullPathFileName.toUtf8().constData());
1864                 rm->currentPlane->image.load(":/images/dummy.png");
1865             }
1866             setTarget(rm->currentPlane->image);
1867             //load his shot or a default shot
1868 
1869             if (rm->shot.IsValid())
1870             {
1871 				fov = (rm->shot.Intrinsics.cameraType == 0) ? rm->shot.GetFovFromFocal() : 5.0;
1872 
1873 				// this code seems useless, and if the camera translation is[0 0 0] (or even just with a small z), there is a division by zero
1874 				//float cameraDist = getCameraDistance();
1875 				//Matrix44f rotFrom;
1876 				//rm->shot.Extrinsics.Rot().ToMatrix(rotFrom);
1877                 //Point3f p1 = rotFrom*(vcg::Point3f::Construct(rm->shot.Extrinsics.Tra()));
1878 				//Point3f p2 = (Point3f(0,0,cameraDist));
1879 				//trackball.track.sca =fabs(p2.Z()/p1.Z());
1880 
1881 				trackball.track.sca = 3.0f / this->md()->bbox().Diag(); // hack, we reset the trackball scale factor to the size of the mesh object
1882 
1883 				/*
1884 				Box3m bb;
1885 				float sceneCamSize = this->md()->bbox().Diag();
1886 				bb.Add(this->md()->bbox());
1887 				bb.Add(rm->shot.Extrinsics.Tra());
1888 				sceneCamSize = bb.Diag();
1889 				trackball.track.sca = 1.0f / sceneCamSize; // hack, we reset the trackball scale factor to the size of the mesh object + viewpoint DOES NOT WORK !
1890 				*/
1891 
1892                 loadShot(QPair<Shotm, float> (rm->shot,trackball.track.sca));
1893             }
1894             else
1895                 createOrthoView("Front");
1896         }
1897 }
1898 
drawTarget()1899 void GLArea::drawTarget()
1900 {
1901 	makeCurrent();
1902     if(!targetTex) return;
1903 
1904     if(this->md()->rm()==0) return;
1905     QImage &curImg = this->md()->rm()->currentPlane->image;
1906     float imageRatio = float(curImg.width())/float(curImg.height());
1907     float screenRatio = float(this->width())/float(this->height());
1908     //set orthogonal view
1909     glPushMatrix();
1910     glLoadIdentity();
1911     glMatrixMode(GL_PROJECTION);
1912     glPushMatrix();
1913     glLoadIdentity();
1914     gluOrtho2D(-1.0f*screenRatio, 1.0f*screenRatio, -1, 1);
1915 
1916     glColor4f(1, 1, 1, opacity);
1917     glDisable(GL_LIGHTING);
1918     glDisable(GL_DEPTH_TEST);
1919     glEnable(GL_BLEND);
1920     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1921     glEnable(GL_TEXTURE_2D);
1922     glBindTexture(GL_TEXTURE_2D, targetTex);
1923     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1924 
1925     glBegin(GL_QUADS);
1926     glTexCoord2f(0.0f, 0.0f);	//first point
1927     glVertex3f(-1.0f*imageRatio, -1.0f, 0.0f);
1928     glTexCoord2f(1.0f, 0.0f);	//second point
1929     glVertex3f(1.0f*imageRatio, -1.0f, 0.0f);
1930     glTexCoord2f(1.0f, 1.0f);	//third point
1931     glVertex3f(1.0f*imageRatio, 1.0f, 0.0f);
1932     glTexCoord2f(0.0f, 1.0f);	//fourth point
1933     glVertex3f(-1.0f*imageRatio, 1.0f, 0.0f);
1934     glEnd();
1935 
1936     glEnable(GL_DEPTH_TEST);
1937     glEnable(GL_LIGHTING);
1938 
1939     glBindTexture(GL_TEXTURE_2D, 0);
1940     glDisable(GL_TEXTURE_2D);
1941 
1942     //restore view
1943     glPopMatrix();
1944     glMatrixMode(GL_MODELVIEW);
1945     glPopMatrix();
1946 }
1947 
1948 
setTarget(QImage & image)1949 void GLArea::setTarget(QImage &image) {
1950 	makeCurrent();
1951     if (image.isNull())
1952         return;
1953     if (targetTex) {
1954         glDeleteTextures(1, &targetTex);
1955         targetTex = 0;
1956     }
1957     // create texture
1958     glGenTextures(1, &targetTex);
1959     QImage tximg = QGLWidget::convertToGLFormat(image);
1960     glBindTexture(GL_TEXTURE_2D, targetTex);
1961     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1962     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1963     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1964     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1965     glTexImage2D(GL_TEXTURE_2D, 0, 3, tximg.width(), tximg.height(),
1966                  0, GL_RGBA, GL_UNSIGNED_BYTE, tximg.bits());
1967 
1968     glBindTexture(GL_TEXTURE_2D, 0);
1969 }
1970 
1971 // --------------- Methods involving shots -------------------------------------
1972 
getCameraDistance()1973 float GLArea::getCameraDistance()
1974 {
1975     float cameraDist = viewRatio() / tanf(vcg::math::ToRad(fov*.5f));
1976     return cameraDist;
1977 }
1978 
initializeShot(Shotm & shot)1979 void GLArea::initializeShot(Shotm &shot)
1980 {
1981     shot.Intrinsics.PixelSizeMm[0]=0.036916077f;
1982     shot.Intrinsics.PixelSizeMm[1]=0.036916077f;
1983 
1984     shot.Intrinsics.DistorCenterPx[0]=width()/2;
1985     shot.Intrinsics.DistorCenterPx[1]=height()/2;
1986     shot.Intrinsics.CenterPx[0]=width()/2;
1987     shot.Intrinsics.CenterPx[1]=height()/2;
1988     shot.Intrinsics.ViewportPx[0]=width();
1989     shot.Intrinsics.ViewportPx[1]=height();
1990 
1991     double viewportYMm = shot.Intrinsics.PixelSizeMm[1]*shot.Intrinsics.ViewportPx[1];
1992     shot.Intrinsics.FocalMm = viewportYMm/(2*tanf(vcg::math::ToRad(this->fovDefault()/2.0f))); //27.846098mm
1993 
1994     shot.Extrinsics.SetIdentity();
1995 }
1996 
readViewFromFile()1997 bool GLArea::readViewFromFile()
1998 {
1999     QString filename = QFileDialog::getOpenFileName(this, tr("Load Project"), "./", tr("Xml Files (*.xml)"));
2000     return GLArea::readViewFromFile(filename);
2001 }
2002 
readViewFromFile(QString const & filename)2003 bool GLArea::readViewFromFile(QString const& filename)
2004 {
2005     QFile qf(filename);
2006     QFileInfo qfInfo(filename);
2007 
2008     if( !qf.open(QIODevice::ReadOnly ) )
2009         return false;
2010 
2011     QString project_path = qfInfo.absoluteFilePath();
2012 
2013     QDomDocument doc("XmlDocument");    //It represents the XML document
2014     if(!doc.setContent( &qf ))
2015         return false;
2016 
2017     QString type = doc.doctype().name();
2018 
2019     //TextAlign file project
2020     if(type == "RegProjectML")   loadShotFromTextAlignFile(doc);
2021     //View State file
2022     else if(type == "ViewState") loadViewFromViewStateFile(doc);
2023 
2024     // qDebug("End file reading");
2025     qf.close();
2026 
2027     return true;
2028 }
2029 
saveViewToFile()2030 bool GLArea::saveViewToFile()
2031 {
2032     QFileDialog saveDiag(this, tr("Save View To File"), "./", tr("View file (*.xml)"));
2033 
2034 #if defined(Q_OS_WIN)
2035     saveDiag.setOption(QFileDialog::DontUseNativeDialog);
2036 #endif
2037     saveDiag.setAcceptMode(QFileDialog::AcceptSave);
2038     saveDiag.exec();
2039     QStringList files = saveDiag.selectedFiles();
2040     if (files.size() != 1)
2041         return false;
2042     QString fileName = files[0];
2043     QFileInfo fi(fileName);
2044     if (fi.isDir())
2045         return false;
2046     if (fi.suffix().isEmpty())
2047     {
2048         QRegExp reg("\\.\\w+");
2049         saveDiag.selectedNameFilter().indexOf(reg);
2050         QString ext = reg.cap();
2051         fileName.append(ext);
2052         fi.setFile(fileName);
2053     }
2054     QDir::setCurrent(fi.absoluteDir().absolutePath());
2055 
2056     bool ret = false;
2057 	qDebug("Saving a file %s\n", qUtf8Printable(fileName));
2058     if (fileName.isEmpty()) return false;
2059     else
2060     {
2061         QFile qFile(fileName);
2062         if (qFile.open(QIODevice::WriteOnly)) {
2063           QTextStream out(&qFile); out << this->viewToText();
2064           qFile.close();
2065           ret = true;
2066         }
2067     }
2068 
2069     if (!ret)
2070       QMessageBox::critical(this, tr("Meshlab Saving Error"), QString("Unable to save view file %1\n").arg(fileName));
2071 
2072     return true;
2073 }
2074 
loadShotFromTextAlignFile(const QDomDocument & doc)2075 void GLArea::loadShotFromTextAlignFile(const QDomDocument &doc)
2076 {
2077     QDomElement root = doc.documentElement();
2078     QDomNode node;
2079     Shotm shot;
2080 
2081     node = root.firstChild();
2082 
2083     //Devices
2084     while(!node.isNull()){
2085         if(QString::compare(node.nodeName(),"Device")==0)
2086         {
2087             QString type = node.attributes().namedItem("type").nodeValue();
2088             if (type== "GlImageWidget")
2089             {
2090                 //Aligned Image
2091                 if(QString::compare(node.attributes().namedItem("aligned").nodeValue(),"1")==0){
2092                     QDomNode nodeb = node.firstChild();
2093                     ReadShotFromOLDXML(shot,nodeb);
2094                 }
2095             }
2096         }
2097         node = node.nextSibling();
2098     }
2099 
2100     //Adjust params for Meshlab settings
2101 
2102     //resize viewport
2103     int w = shot.Intrinsics.ViewportPx[0];
2104     int h = shot.Intrinsics.ViewportPx[1];
2105 
2106     shot.Intrinsics.DistorCenterPx[0]=w/2;
2107     shot.Intrinsics.DistorCenterPx[1]=h/2;
2108     shot.Intrinsics.CenterPx[0]=w/2;
2109     shot.Intrinsics.CenterPx[1]=h/2;
2110     shot.Intrinsics.ViewportPx[0]=w;
2111     shot.Intrinsics.ViewportPx[1]=h;
2112 
2113     // The shot loaded from TextAlign doesn't have a scale. Trackball needs it.
2114     // The scale factor is computed as the ratio between cameraDistance and the z coordinate of the translation
2115     // introduced by the shot.
2116 	fov = (shot.Intrinsics.cameraType == 0) ? shot.GetFovFromFocal() : 5.0;
2117 
2118     // float cameraDist = getCameraDistance();
2119 
2120     Matrix44f rotFrom;
2121     shot.Extrinsics.Rot().ToMatrix(rotFrom);
2122 
2123 	// this code seems useless, and if the camera translation is[0 0 0] (or even just with a small z), there is a division by zero
2124 	//Point3f p1 = rotFrom*(vcg::Point3f::Construct(rm->shot.Extrinsics.Tra()));
2125 	//Point3f p2 = (Point3f(0,0,cameraDist));
2126 	//trackball.track.sca =fabs(p2.Z()/p1.Z());
2127 
2128     loadShot(QPair<Shotm, float> (shot,trackball.track.sca));
2129 
2130 }
2131 
2132 /*
2133 ViewState file is an xml file format created by Meshlab with the action "copyToClipboard"
2134 */
loadViewFromViewStateFile(const QDomDocument & doc)2135 void GLArea::loadViewFromViewStateFile(const QDomDocument &doc)
2136 {
2137     Shotm shot;
2138     QDomElement root = doc.documentElement();
2139     QDomNode node = root.firstChild();
2140 
2141     while(!node.isNull())
2142     {
2143         if (QString::compare(node.nodeName(),"VCGCamera")==0)
2144             ReadShotFromQDomNode(shot,node);
2145         else if (QString::compare(node.nodeName(),"CamParam")==0)
2146             ReadShotFromOLDXML(shot,node);
2147 
2148         else if (QString::compare(node.nodeName(),"ViewSettings")==0)
2149         {
2150             QDomNamedNodeMap attr = node.attributes();
2151             trackball.track.sca = attr.namedItem("TrackScale").nodeValue().section(' ',0,0).toFloat();
2152             nearPlane = attr.namedItem("NearPlane").nodeValue().section(' ',0,0).toFloat();
2153             farPlane = attr.namedItem("FarPlane").nodeValue().section(' ',0,0).toFloat();
2154 			fov = (shot.Intrinsics.cameraType == 0) ? shot.GetFovFromFocal() : 5.0;
2155             clipRatioNear = nearPlane/getCameraDistance();
2156             clipRatioFar = farPlane/getCameraDistance();
2157         }
2158         /*else if (QString::compare(node.nodeName(),"Render")==0)
2159         {
2160         QDomNamedNodeMap attr = node.attributes();
2161         rm.drawMode = (vcg::GLW::DrawMode) (attr.namedItem("DrawMode").nodeValue().section(' ',0,0).toInt());
2162         rm.colorMode = (vcg::GLW::ColorMode) (attr.namedItem("ColorMode").nodeValue().section(' ',0,0).toInt());
2163         rm.textureMode = (vcg::GLW::TextureMode) (attr.namedItem("TextureMode").nodeValue().section(' ',0,0).toInt());
2164         rm.lighting = (attr.namedItem("Lighting").nodeValue().section(' ',0,0).toInt() != 0);
2165         rm.backFaceCull = (attr.namedItem("BackFaceCull").nodeValue().section(' ',0,0).toInt() != 0);
2166         rm.doubleSideLighting = (attr.namedItem("DoubleSideLighting").nodeValue().section(' ',0,0).toInt() != 0);
2167         rm.fancyLighting = (attr.namedItem("FancyLighting").nodeValue().section(' ',0,0).toInt() != 0);
2168         }*/
2169         node = node.nextSibling();
2170     }
2171 
2172     loadShot(QPair<Shotm, float> (shot,trackball.track.sca));
2173 }
viewToText()2174 QString GLArea::viewToText()
2175 {
2176     QString docString;
2177 
2178     Shotm shot = shotFromTrackball().first;
2179 
2180     QDomDocument doc("ViewState");
2181     QDomElement root = doc.createElement("project");
2182     doc.appendChild( root );
2183 
2184     QDomElement shotElem = WriteShotToQDomNode(shot,doc);
2185     root.appendChild(shotElem);
2186 
2187     QDomElement settingsElem = doc.createElement( "ViewSettings" );
2188     settingsElem.setAttribute( "TrackScale", trackball.track.sca);
2189     settingsElem.setAttribute( "NearPlane", nearPlane);
2190     settingsElem.setAttribute( "FarPlane", farPlane);
2191     root.appendChild(settingsElem);
2192 
2193     /*QDomElement renderElem = doc.createElement( "Render");
2194     renderElem.setAttribute("DrawMode",rm.drawMode);
2195     renderElem.setAttribute("ColorMode",rm.colorMode);
2196     renderElem.setAttribute("TextureMode",rm.textureMode);
2197     renderElem.setAttribute("Lighting",rm.lighting);
2198     renderElem.setAttribute("BackFaceCull",rm.backFaceCull);
2199     renderElem.setAttribute("DoubleSideLighting",rm.doubleSideLighting);
2200     renderElem.setAttribute("FancyLighting",rm.fancyLighting);
2201     root.appendChild(renderElem);*/
2202 
2203     return doc.toString();
2204 }
2205 
viewToClipboard()2206 void GLArea::viewToClipboard()
2207 {
2208     QApplication::clipboard()->setText(this->viewToText());
2209 }
2210 
viewFromClipboard()2211 void GLArea::viewFromClipboard()
2212 {
2213     QClipboard *clipboard = QApplication::clipboard();
2214     QString shotString = clipboard->text();
2215     QDomDocument doc("StringDoc");
2216     doc.setContent(shotString);
2217     loadViewFromViewStateFile(doc);
2218 }
2219 
shotFromTrackball()2220 QPair<Shotm,float> GLArea::shotFromTrackball()
2221 {
2222     Shotm shot;
2223     initializeShot(shot);
2224 
2225     double viewportYMm=shot.Intrinsics.PixelSizeMm[1]*shot.Intrinsics.ViewportPx[1];
2226     shot.Intrinsics.FocalMm = viewportYMm/(2*tanf(vcg::math::ToRad(fov/2)));
2227 
2228 	// in MeshLab, fov < 5.0 means orthographic camera
2229 	if (fov > 5.0)
2230 		shot.Intrinsics.cameraType = 0; //perspective
2231 	else
2232 		shot.Intrinsics.cameraType = 1; //orthographic
2233 
2234     float cameraDist = getCameraDistance();
2235 
2236     //add the translation introduced by gluLookAt() (0,0,cameraDist), in order to have te same view---------------
2237     //T(gl)*S*R*T(t) => SR(gl+t) => S R (S^(-1)R^(-1)gl + t)
2238     //Add translation S^(-1) R^(-1)(gl)
2239     //Shotd doesn't introduce scaling
2240     //---------------------------------------------------------------------
2241     shot.Extrinsics.SetTra( shot.Extrinsics.Tra() + (Inverse(shot.Extrinsics.Rot())*Point3m(0, 0, cameraDist)));
2242 
2243     Shotm newShot = track2ShotCPU<Shotm::ScalarType>(shot, &trackball);
2244 
2245     return QPair<Shotm, float> (newShot,trackball.track.sca);
2246 }
2247 
viewFromCurrentShot(QString kind)2248 void GLArea::viewFromCurrentShot(QString kind)
2249 {
2250     Shotm localShot;
2251     if(kind=="Mesh" && this->md()->mm())   localShot = this->md()->mm()->cm.shot;
2252     if(kind=="Raster" && this->md()->rm()) localShot = this->md()->rm()->shot;
2253     if(!localShot.IsValid())
2254     {
2255         this->Logf(GLLogStream::SYSTEM, "Unable to set Shot from current %s", qUtf8Printable(kind));
2256         return;
2257     }
2258 
2259     loadShot(QPair<Shotm, float>(localShot,trackball.track.sca));
2260 }
2261 
2262 
loadShot(const QPair<Shotm,float> & shotAndScale)2263 void GLArea::loadShot(const QPair<Shotm,float> &shotAndScale){
2264 
2265     Shotm shot = shotAndScale.first;
2266 
2267 	fov = (shot.Intrinsics.cameraType == 0) ? shot.GetFovFromFocal() : 5.0;
2268 
2269     float cameraDist = getCameraDistance();
2270 
2271     //reset trackball. The point of view must be set only by the shot
2272     trackball.Reset();
2273     trackball.track.sca = shotAndScale.second;
2274 
2275     shot2Track(shot, cameraDist, trackball);
2276 
2277 	/*Point3f point = this->md()->bbox().Center();
2278 	Point3f p1 = ((trackball.track.Matrix()*(point-trackball.center))- Point3f(0,0,cameraDist));*/
2279     //Expressing the translation along Z with a scale factor k
2280     //Point3f p2 = ((trackball.track.Matrix()*(point-trackball.center))- Point3f(0,0,cameraDist));
2281 
2282     ////k is the ratio between the distances along z of two correspondent points (before and after the traslation)
2283     ////from the point of view
2284     //float k= abs(p2.Z()/p1.Z());
2285 
2286     //float sca= trackball.track.sca/k;
2287     //Point3f tra = trackball.track.tra;
2288     //
2289     //// Apply this formula:
2290     //// SR(t+p) -v = k[S'R'(t'+p) -v] forall p, R=R', k is a constant
2291     //// SR(t) -v = k[S'R(t') -v]
2292     //// t' = 1/k* S'^-1St + (k-1)/k S'^-1*R^-1v
2293     //Matrix44f s0 = Matrix44f().SetScale(trackball.track.sca,trackball.track.sca, trackball.track.sca);
2294     //Matrix44f s1 = Matrix44f().SetScale(sca, sca, sca);
2295     //Matrix44f r;
2296     //trackball.track.rot.ToMatrix(r);
2297     //Matrix44f rapM = Matrix44f().SetScale(1/k, 1/k, 1/k);
2298     //Matrix44f rapM2 = Matrix44f().SetScale(1-1/k, 1-1/k, 1-1/k);
2299     //Point3f t1 = rapM*Inverse(s1)*s0*tra + rapM2*Inverse(s1)*Inverse(r)*Point3f(0,0,cameraDist);
2300 
2301     //trackball.track.sca =sca;
2302     //trackball.track.tra =t1 /*+ tb.track.rot.Inverse().Rotate(glLookAt)*/ ;
2303 
2304     update();
2305 }
2306 
createOrthoView(QString dir)2307 void GLArea::createOrthoView(QString dir)
2308 {
2309     Shotm view;
2310     initializeShot(view);
2311 
2312     fov =5;
2313     double viewportYMm = view.Intrinsics.PixelSizeMm[1]*view.Intrinsics.ViewportPx[1];
2314     view.Intrinsics.FocalMm = viewportYMm/(2*tanf(vcg::math::ToRad(fov/2))); //27.846098 equivalente a circa 60 gradi
2315 
2316     trackball.Reset();
2317     float newScale= 3.0f/this->md()->bbox().Diag();
2318     trackball.track.sca = newScale;
2319     trackball.track.tra.Import(-this->md()->bbox().Center());
2320 
2321     Matrix44m rot;
2322 
2323     if(dir == tr("Top"))
2324         rot.SetRotateDeg(90,Point3m(1,0,0));
2325     else if(dir == tr("Bottom"))
2326         rot.SetRotateDeg(90,Point3m(-1,0,0));
2327     else if(dir == tr("Left"))
2328         rot.SetRotateDeg(90,Point3m(0,1,0));
2329     else if(dir == tr("Right"))
2330         rot.SetRotateDeg(90,Point3m(0,-1,0));
2331     else if(dir == tr("Front"))
2332         rot.SetRotateDeg(0,Point3m(0,1,0));
2333     else if(dir == tr("Back"))
2334         rot.SetRotateDeg(180,Point3m(0,1,0));
2335 	// scene uses "engineering" reference system, with Z as vertical axis
2336 	else if (dir == tr("Top (Z is up)"))
2337 		rot.SetRotateDeg(0, Point3m(1, 0, 0));
2338 	else if (dir == tr("Bottom (Z is up)"))
2339 		rot.SetRotateDeg(180, Point3m(1, 0, 0));
2340 	else if (dir == tr("Left (Z is up)"))
2341 		rot = Matrix44m().SetRotateDeg(90, Point3m(0, 1, 0)) * Matrix44m().SetRotateDeg(90, Point3m(-1, 0, 0));
2342 	else if (dir == tr("Right (Z is up)"))
2343 		rot = Matrix44m().SetRotateDeg(90, Point3m(0, -1, 0)) * Matrix44m().SetRotateDeg(90, Point3m(-1, 0, 0));
2344 	else if (dir == tr("Front (Z is up)"))
2345 		rot.SetRotateDeg(90, Point3m(-1, 0, 0));
2346 	else if (dir == tr("Back (Z is up)"))
2347 		rot = Matrix44m().SetRotateDeg(90, Point3m(1, 0, 0)) * Matrix44m().SetRotateDeg(180, Point3m(0, 1, 0));
2348 
2349     view.Extrinsics.SetRot(rot);
2350 
2351     float cameraDist = getCameraDistance();
2352 
2353     //add the translation introduced by gluLookAt() (0,0,cameraDist), in order to have te same view---------------
2354     //T(gl)*S*R*T(t) => SR(gl+t) => S R (S^(-1)R^(-1)gl + t)
2355     //Add translation S^(-1) R^(-1)(gl)
2356     //Shotd doesn't introduce scaling
2357     //---------------------------------------------------------------------
2358     view.Extrinsics.SetTra( view.Extrinsics.Tra() + (Inverse(view.Extrinsics.Rot())*Point3m(0, 0, cameraDist)));
2359 
2360     Shotm shot = track2ShotCPU(view, &trackball);
2361 
2362     QPair<Shotm,float> shotAndScale = QPair<Shotm,float> (shot, trackball.track.sca);
2363     loadShot(shotAndScale);
2364 
2365 	this->Logf(GLLogStream::SYSTEM, "View scene from %s", qUtf8Printable(dir));
2366 }
2367 
toggleOrtho()2368 void GLArea::toggleOrtho()
2369 {
2370 	if (fov == 5.0)
2371 		fov = 35.0;
2372 	else
2373 		fov = 5.0;
2374 
2375 	update();
2376 }
2377 
trackballStep(QString dir)2378 void GLArea::trackballStep(QString dir)
2379 {
2380 	float stepAngle = float(M_PI / 12.0);
2381 
2382 	if (dir == tr("Horizontal +"))
2383 		trackball.track.rot = Quaternionf(-stepAngle, Point3f(0.0, 1.0, 0.0)) * trackball.track.rot;
2384 	else if (dir == tr("Horizontal -"))
2385 		trackball.track.rot = Quaternionf( stepAngle, Point3f(0.0, 1.0, 0.0)) * trackball.track.rot;
2386 	else if (dir == tr("Vertical +"))
2387 		trackball.track.rot = Quaternionf(-stepAngle, Point3f(1.0, 0.0, 0.0)) * trackball.track.rot;
2388 	else if (dir == tr("Vertical -"))
2389 		trackball.track.rot = Quaternionf( stepAngle, Point3f(1.0, 0.0, 0.0)) * trackball.track.rot;
2390 	else if (dir == tr("Axial +"))
2391 		trackball.track.rot = Quaternionf(-stepAngle, Point3f(0.0, 0.0, 1.0)) * trackball.track.rot;
2392 	else if (dir == tr("Axial -"))
2393 		trackball.track.rot = Quaternionf( stepAngle, Point3f(0.0, 0.0, 1.0)) * trackball.track.rot;
2394 
2395 	update();
2396 }
2397 
2398 
2399 //MultiViewer_Container * GLArea::mvc()
2400 //{
2401 //	QObject * curParent = this->parent();
2402 //	while(qobject_cast<MultiViewer_Container *>(curParent) == 0)
2403 //	{
2404 //		if (curParent != NULL)
2405 //			curParent = curParent->parent();
2406 //		else
2407 //			return NULL;
2408 //	}
2409 //	return qobject_cast<MultiViewer_Container *>(curParent);
2410 //}
2411 
2412 
showInterruptButton() const2413 bool GLArea::showInterruptButton() const
2414 {
2415     return interrbutshow;
2416 }
2417 
showInterruptButton(const bool & show)2418 void GLArea::showInterruptButton( const bool& show )
2419 {
2420     interrbutshow = show;
2421 }
2422 
completeUpdateRequested()2423 void GLArea::completeUpdateRequested()
2424 {
2425     makeCurrent();
2426     if ((this->md() != NULL) && (this->md()->rm() != NULL))
2427         loadRaster(this->md()->rm()->id());
2428     //if (md()->mm() != NULL)
2429     //	trackball.center = md()->mm()->cm.bbox.Center();
2430     update();
2431     //doneCurrent();
2432 }
2433 
2434 //RenderMode* GLArea::getCurrentRenderMode()
2435 //{
2436 //	if ((md() != NULL) && (md()->mm() != NULL))
2437 //	{
2438 //		QMap<int,RenderMode>::iterator it = rendermodemap.find(md()->mm()->id());
2439 //		if (it != rendermodemap.end())
2440 //			return &it.value();
2441 //	}
2442 //	return NULL;
2443 //}
2444 
meshAdded(int)2445 void GLArea::meshAdded( int /*index*/)
2446 {
2447     emit updateLayerTable();
2448 }
2449 
meshRemoved(int)2450 void GLArea::meshRemoved( int /*index*/ )
2451 {
2452     emit updateLayerTable();
2453 }
2454 
setupTextureEnv(GLuint textid)2455 void GLArea::setupTextureEnv( GLuint textid )
2456 {
2457     makeCurrent();
2458     glPushAttrib(GL_ENABLE_BIT);
2459     glEnable(GL_TEXTURE_2D);
2460     glBindTexture(GL_TEXTURE_2D,textid);
2461     if(glas.textureMagFilter == 0 )
2462         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
2463     else
2464         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
2465     if(glas.textureMinFilter == 0 )
2466         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
2467     else
2468         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
2469 
2470     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2471     glBindTexture(GL_TEXTURE_2D,0);
2472     glPopAttrib();
2473 }
2474 
mw()2475 MainWindow * GLArea::mw()
2476 {
2477     QObject * curParent = parent();
2478     while(qobject_cast<MainWindow *>(curParent) == 0)
2479     {
2480         curParent = curParent->parent();
2481     }
2482     return qobject_cast<MainWindow *>(curParent);
2483 }
2484 
2485