diff --git a/src/meshlab_20/glarea.cpp b/src/meshlab_20/glarea.cpp index 14e17e071..6333e8397 100644 --- a/src/meshlab_20/glarea.cpp +++ b/src/meshlab_20/glarea.cpp @@ -258,18 +258,18 @@ void GLArea::paintGL() setView(); // Set Modelview and Projection matrix drawGradient(); // draws the background - drawLight(); + drawLight(); glPushMatrix(); // Finally apply the Trackball for the model trackball.GetView(); - trackball.Apply(false); + trackball.Apply(false); glPushMatrix(); //glScale(d); - // glTranslate(-FullBBox.Center()); - setLightModel(); + //glTranslate(-FullBBox.Center()); + setLightModel(); // Set proper colorMode if(rm.colorMode != GLW::CMNone) @@ -680,6 +680,16 @@ void GLArea::mouseReleaseEvent(QMouseEvent*e) update(); if(isCurrent()) mvc->updateReleaseViewers(e); + + //TestShot + Shot shot1; initializeShot(shot1); + Shot shot2; initializeShot(shot2); + shot1.Extrinsics.SetTra(Point3(0,0,10)); + shot2.Extrinsics.SetTra(Point3(0,0,10)); + + shot1 = getShotFromTrack(shot1,&trackball); + shot2 = getShotFromTrack2(shot2, &trackball); + } //Processing of tablet events, interesting only for painting plugins @@ -1022,3 +1032,108 @@ void GLArea::initGlobalParameterSet( RichParameterSet * defaultGlobalParamSet) GLAreaSetting::initGlobalParameterSet(defaultGlobalParamSet); } + +void GLArea::initializeShot(Shot &shot) +{ + + //Da vedere + shot.Intrinsics.PixelSizeMm[0]=0.036916077; + shot.Intrinsics.PixelSizeMm[1]=0.036916077; + + shot.Intrinsics.FocalMm= 27.846098; //per avere circa 60 gradi + shot.Intrinsics.DistorCenterPx[0]=width()/2; + shot.Intrinsics.DistorCenterPx[1]=height()/2; + shot.Intrinsics.CenterPx[0]=width()/2; + shot.Intrinsics.CenterPx[1]=height()/2; + shot.Intrinsics.ViewportPx[0]=width(); + shot.Intrinsics.ViewportPx[1]=height(); + + shot.Extrinsics.SetIdentity(); + + //Shot newshot; + //vcg::Box3 box; + //box.Import(meshDoc->bbox()); + //newshot.Extrinsics.SetIdentity(); + //vcg::Point3d c = box.Center(); + //vcg::Point3d v = c - vcg::Point3d(0, 0, 3*box.Diag()); + //newshot.SetViewPoint(v); + //newshot.LookAt(c, vcg::Point3d(0, 1, 0)); + + + //vcg::Camera &cam = shot.Intrinsics; + //double dx = cam.ViewportPx[0]*cam.PixelSizeMm[0]; + + ////if we have the focal we compute the angle (and viceversa) + //cout << "Focal: " << cam.FocalMm << endl; + //cout << "dx: " << dx << endl; + //double angle = 60.0; + //if(dx != 0 && cam.FocalMm != 0) { //we have the focal + // angle = atan(dx/cam.FocalMm)*180.0f/M_PI; + //} else if(dx != 0) { + // cam.FocalMm = dx/tan(angle*M_PI/180.0f); + //} else { + // cam.FocalMm = 60; + //} + + //cout << "Angle: " << angle << endl; + //cout << "Focal: " << cam.FocalMm << endl; + //cout << endl; + + //newshot.Intrinsics.SetPerspective(angle/2, width()/(double)height(), cam.FocalMm, vcg::Point2(width(), height())); + //vcg::Camera &cam1 = newshot.Intrinsics; + //double dx1 = cam.ViewportPx[0]*cam1.PixelSizeMm[0]; + //cout << "Dx now: " << dx1 << " fcal: " << newshot.Intrinsics.FocalMm << endl; + //return newshot; +} + +void GLArea::loadShot(){ + //Shot test + Shot shot; + initializeShot(shot); + //oppure lo leggi da file + + double viewportYMm=shot.Intrinsics.PixelSizeMm[1]*shot.Intrinsics.ViewportPx[1]; + fov = 2*(vcg::math::ToDeg(atanf(viewportYMm/(2*shot.Intrinsics.FocalMm)))); + /*fov=60; + float focal = viewportYMm/(2*tanf(vcg::math::ToRad(fov/2)));*/ + + // This parameter is the one that controls: + // HOW LARGE IS THE TRACKBALL ICON ON THE SCREEN. + float viewRatio = 1.75f; + float cameraDist = viewRatio / tanf(vcg::math::ToRad(fov*.5f)); + + //Esempi di shot di ingresso + //shot.Extrinsics.SetTra(Point3d(0, 0, cameraDist)); + vcg::Matrix44d rot; + rot.Identity(); + rot.SetRotateDeg(90,Point3(0,1,0)); + shot.Extrinsics.SetRot(rot); + shot.Extrinsics.SetTra(Inverse(rot)*Point3d(0, 0, cameraDist)); + + //correct the traslation introduced by gluLookAt() (0,0,cameraDist)--------------------------------------- + //T(gl) S R T(t) => S R T(S^(-1) R^(-1)(gl) + t) + //Shot doesn't introduce scaling + //To compensate S^(-1) R^(-1)(gl)we add to t S^(-1) R^(-1)(-gl) + shot.Extrinsics.SetTra(shot.Extrinsics.Tra() + (Inverse(shot.Extrinsics.Rot())*Point3d(0, 0, -cameraDist))); + + //reset trackball. The point of view must be set only by the shot + trackball.Reset(); + float newScale= 3.0f/meshDoc->bbox().Diag(); + trackball.track.sca = newScale; + trackball.track.tra = -meshDoc->bbox().Center(); + + Shot2Track(shot, cameraDist,trackball); + + //Test on trackball + /*Matrix44f s_inv = Matrix44f().SetScale(1/trackball.track.sca, 1/trackball.track.sca, 1/trackball.track.sca); + vcg::Matrix44f rot_inv; + Inverse(trackball.track.rot).ToMatrix(rot_inv); + + Shot2Track(shot, cameraDist,trackball); + + trackball.track.tra += s_inv*rot_inv*Point3f(0, 0, cameraDist);*/ + + //Shot2Track(shot, cameraDist,trackball); + + updateGL(); +} diff --git a/src/meshlab_20/glarea.h b/src/meshlab_20/glarea.h index b7a4bd24b..94918b705 100644 --- a/src/meshlab_20/glarea.h +++ b/src/meshlab_20/glarea.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include "../common/interfaces.h" #include "../common/filterscript.h" @@ -42,6 +44,9 @@ #include "viewer.h" #include "multiViewer_Container.h" +//mathematics +#include + #define SSHOT_BYTES_PER_PIXEL 4 enum LightingModel{LDOUBLE,LFANCY}; @@ -69,6 +74,8 @@ class GLArea : public QGLWidget, public Viewer { Q_OBJECT + typedef vcg::Shot Shot; + public: GLArea(QWidget *parent, MultiViewer_Container *mvcont, RichParameterSet *current, int id, MeshDocument *meshDoc); ~GLArea(); @@ -127,6 +134,7 @@ public: void setLightModel(); void setView(); void resetTrackBall(); + void loadShot(); std::list iDecoratorsList; void setRenderer(MeshRenderInterface *rend, QAction *shader){ iRenderer = rend; currentShader = shader;} @@ -309,7 +317,144 @@ private: int tileCol, tileRow, totalCols, totalRows; void setCursorTrack(vcg::TrackMode *tm); - + void initializeShot(Shot &shot); + + /* + Given a shot "refCamera" and a trackball "track", computes a new shot which is equivalent + to apply "refCamera" o "track". + */ + template + vcg::Shot getShotFromTrack(vcg::Shot &refCamera, vcg::Trackball *track){ + vcg::Shot view; + + double _near, _far; + _near = 0.1; + _far = 100; + + //get OpenGL modelview matrix after applying the trackball + GlShot >::SetView(refCamera, _near, _far); + glPushMatrix(); + track->GetView(); + track->Apply(); + vcg::Matrix44d model; + glGetv(GL_MODELVIEW_MATRIX, model); + glPopMatrix(); + GlShot >::UnsetView(); + + //get translation out of modelview + vcg::Point3d tra; + tra[0] = model[0][3]; tra[1] = model[1][3]; tra[2] = model[2][3]; + model[0][3] = model[1][3] = model[2][3] = 0; + + //get pure rotation out of modelview + double det = model.Determinant(); + double idet = 1/pow(det, 1/3.0); //inverse of the determinant + model *= idet; + model[3][3] = 1; + view.Extrinsics.SetRot(model); + + //get pure translation out of modelview + vcg::Matrix44d imodel = model; + vcg::Transpose(imodel); + tra = -(imodel*tra); + tra *= idet; + view.Extrinsics.SetTra(vcg::Point3::Construct(tra)); + + //use same current intrinsics + view.Intrinsics = refCamera.Intrinsics; + + return view; + } + + /* + Given a shot "refCamera" and a trackball "track", computes a new shot which is equivalent + to apply "refCamera" o "track". + */ + template + vcg::Shot getShotFromTrack2(vcg::Shot &refCamera, vcg::Trackball *track){ + vcg::Shot view; + + double _near, _far; + _near = 0.1; + _far = 100; + + //---------------------- ALTERED-------------------- + + // //get OpenGL modelview matrix after applying the trackball + // GlShot >::SetView(refCamera, _near, _far); + // glPushMatrix(); + // track->GetView(); + // track->Apply(); + // vcg::Matrix44d model; + // glGetv(GL_MODELVIEW_MATRIX, model); + // glPopMatrix(); + // GlShot >::UnsetView(); + + //GlShot >::SetView(refCamera, _near, _far); //mi serve per la proj di refcamera... altrimenti come la ottengo? + vcg::Matrix44f shotExtr; + refCamera.GetWorldToExtrinsicsMatrix().ToMatrix(shotExtr); + + ////legge la matrice di proj settata prima + //vcg::Matrix44f proj; + //glGetv(GL_PROJECTION_MATRIX,proj); + //GlShot >::UnsetView(); + + ////aggiorna la matrice di rototraslazione di track + //int viewport[] = {0,0,width(),height()}; + //track->camera.SetView(proj.V(),shotExtr.V(), viewport); + + vcg::Matrix44f model2; + model2 = (shotExtr)* track->Matrix(); + vcg::Matrix44d model; + model2.ToMatrix(model); + + //---------------------- ORIGINAL-------------------- + + //get translation out of modelview + vcg::Point3d tra; + tra[0] = model[0][3]; tra[1] = model[1][3]; tra[2] = model[2][3]; + model[0][3] = model[1][3] = model[2][3] = 0; + + //get pure rotation out of modelview + double det = model.Determinant(); + double idet = 1/pow(det, 1/3.0); //inverse of the determinant + model *= idet; + model[3][3] = 1; + view.Extrinsics.SetRot(model); + + //get pure translation out of modelview + vcg::Matrix44d imodel = model; + vcg::Transpose(imodel); + tra = -(imodel*tra); + tra *= idet; + view.Extrinsics.SetTra(vcg::Point3::Construct(tra)); + + //use same current intrinsics + view.Intrinsics = refCamera.Intrinsics; + + return view; + } + + /* + Given a Shot "from", and a trackball "tb" replaces "tb" with a trackball "tb'" such that: + "from" o "tb" = "tb'" + */ + template + void Shot2Track(const vcg::Shot &from, const float cameraDist, vcg::Trackball &tb){ + + Shot id; + + vcg::Quaterniond qto; qto.FromMatrix(id.Extrinsics.Rot()); + vcg::Quaterniond qfrom; qfrom.FromMatrix(from.Extrinsics.Rot()); + + /*float sca=tb.track.sca; + tb.track.sca=1;*/ + tb.track.tra += ( tb.track.rot.Inverse().Rotate( vcg::Point3f::Construct(-from.Extrinsics.Tra()) + tb.center ) ) / tb.track.sca; + tb.track.rot = vcg::Quaternionf::Construct(qto.Inverse() * qfrom) * tb.track.rot; + tb.track.tra -= ( tb.track.rot.Inverse().Rotate( vcg::Point3f::Construct(- id.Extrinsics.Tra()) + tb.center ) ) / tb.track.sca; + + //aggiustare sca e tra per mettere il centro della trackbal al punto giusto + } }; diff --git a/src/meshlab_20/images/camera.png b/src/meshlab_20/images/camera.png new file mode 100644 index 000000000..1568c7938 Binary files /dev/null and b/src/meshlab_20/images/camera.png differ diff --git a/src/meshlab_20/mainwindow.h b/src/meshlab_20/mainwindow.h index 47ef96b87..ed5f01063 100644 --- a/src/meshlab_20/mainwindow.h +++ b/src/meshlab_20/mainwindow.h @@ -110,6 +110,7 @@ private slots: void toggleBackFaceCulling(); void toggleSelectFaceRendering(); void toggleSelectVertRendering(); + void loadShot(); //void applyDecorateMode(); ///////////Slot Menu View //////////////////////// void fullScreen(); @@ -296,6 +297,8 @@ private: QAction *colorModePerMeshAct; QAction *colorModePerVertexAct; QAction *colorModePerFaceAct; + + QAction *loadShotAct; ///////////Actions Menu View //////////////////////// QAction *fullScreenAct; QAction *showToolbarStandardAct; diff --git a/src/meshlab_20/mainwindow_Init.cpp b/src/meshlab_20/mainwindow_Init.cpp index 57685be2a..fcbcf21fc 100644 --- a/src/meshlab_20/mainwindow_Init.cpp +++ b/src/meshlab_20/mainwindow_Init.cpp @@ -205,6 +205,12 @@ void MainWindow::createActions() setSelectVertRenderingAct->setShortcutContext(Qt::ApplicationShortcut); connect(setSelectVertRenderingAct, SIGNAL(triggered()), this, SLOT(toggleSelectVertRendering())); + loadShotAct = new QAction(QIcon(":/images/camera.png"),tr("Load Shot"),this); + loadShotAct->setCheckable(false); + loadShotAct->setShortcutContext(Qt::ApplicationShortcut); + loadShotAct->setShortcut(Qt::CTRL+Qt::Key_W); + connect(loadShotAct, SIGNAL(triggered()), this, SLOT(loadShot())); + //////////////Action Menu View //////////////////////////////////////////////////////////////////////////// fullScreenAct = new QAction (tr("&FullScreen"), this); fullScreenAct->setCheckable(true); @@ -324,8 +330,10 @@ void MainWindow::createToolBars() renderToolBar->addActions(renderModeGroupAct->actions()); renderToolBar->addAction(renderModeTextureAct); renderToolBar->addAction(setLightAct); - renderToolBar->addAction(setSelectFaceRenderingAct); - renderToolBar->addAction(setSelectVertRenderingAct); + renderToolBar->addAction(setSelectFaceRenderingAct); + renderToolBar->addAction(setSelectVertRenderingAct); + + renderToolBar->addAction(loadShotAct); /*editToolBar = addToolBar(tr("Edit")); editToolBar->addAction(suspendEditModeAct); @@ -439,6 +447,9 @@ void MainWindow::createMenus() renderMenu->addSeparator(); + //Shot SUBmenu + renderMenu ->addAction(loadShotAct); + //////////////////// Menu View //////////////////////////////////////////////////////////////////////////// viewMenu = menuBar()->addMenu(tr("&View")); viewMenu->addAction(fullScreenAct); diff --git a/src/meshlab_20/mainwindow_RunTime.cpp b/src/meshlab_20/mainwindow_RunTime.cpp index bfe1f1ff4..4a9216d54 100644 --- a/src/meshlab_20/mainwindow_RunTime.cpp +++ b/src/meshlab_20/mainwindow_RunTime.cpp @@ -1172,6 +1172,8 @@ void MainWindow::setUnsplit() updateMenus(); } +void MainWindow::loadShot() { GLA()->loadShot(); } + void MainWindow::renderBbox() { GLA()->setDrawMode(GLW::DMBox ); } void MainWindow::renderPoint() { GLA()->setDrawMode(GLW::DMPoints ); } void MainWindow::renderWire() { GLA()->setDrawMode(GLW::DMWire ); } diff --git a/src/meshlab_20/meshlab.qrc b/src/meshlab_20/meshlab.qrc index 42d21341e..9db1fd6f8 100644 --- a/src/meshlab_20/meshlab.qrc +++ b/src/meshlab_20/meshlab.qrc @@ -2,6 +2,7 @@ images/backlines.png images/bbox.png + images/camera.png images/cursors/plain.png images/cursors/plain_pan.png images/cursors/plain_trackball.png