Introduced shot exchange between viewers.

New Operations:
- Link viewers together
- View from main orthogonal views (top, front, etc..)
- Load shot/view from TextAlign file and ViewState file
- Copy/paste view state on/from clipboard
This commit is contained in:
Michele Sottile sottile 2010-07-09 16:43:27 +00:00
parent 9968097c4b
commit 132fa1abe2
5 changed files with 650 additions and 15 deletions

View File

@ -365,6 +365,11 @@ void GLArea::paintGL()
if(error) {
log->Logf(GLLogStream::WARNING,"There are gl errors");
}
//check if viewers are linked
MainWindow *window = (MainWindow*) QApplication::activeWindow();
if(window && window->linkViewersAct->isChecked())
mvc->updateTrackballInViewers();
}
void GLArea::displayInfo()
@ -652,18 +657,20 @@ void GLArea::mousePressEvent(QMouseEvent*e)
void GLArea::mouseMoveEvent(QMouseEvent*e)
{
if( (iEdit && !suspendedEditor) )
iEdit->mouseMoveEvent(e,*mm(),this);
else {
if (isDefaultTrackBall())
{
trackball.MouseMove(e->x(),height()-e->y());
setCursorTrack(trackball.current_mode);
}
else trackball_light.MouseMove(e->x(),height()-e->y());
update();
}
if( (iEdit && !suspendedEditor) )
iEdit->mouseMoveEvent(e,*mm(),this);
else {
if (isDefaultTrackBall())
{
trackball.MouseMove(e->x(),height()-e->y());
setCursorTrack(trackball.current_mode);
}
else trackball_light.MouseMove(e->x(),height()-e->y());
update();
}
}
// When mouse is released we set the correct mouse cursor
void GLArea::mouseReleaseEvent(QMouseEvent*e)
{
@ -896,6 +903,7 @@ void GLArea::setView()
// HOW LARGE IS THE TRACKBALL ICON ON THE SCREEN.
float viewRatio = 1.75f;
float cameraDist = viewRatio / tanf(vcg::math::ToRad(fov*.5f));
if(fov==5)
cameraDist = 1000; // small hack for orthographic projection where camera distance is rather meaningless...
nearPlane = cameraDist - 2.f*clipRatioNear;
@ -1055,3 +1063,434 @@ void GLArea::updateLayerSetVisibility(int meshId, bool visibility)
{
visibilityMap.insert(meshId,visibility);
}
// --------------- Methods involving shots -------------------------------------
float GLArea::getCameraDistance()
{
// 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));
return cameraDist;
}
void GLArea::initializeShot(Shot &shot)
{
//Da vedere
shot.Intrinsics.PixelSizeMm[0]=0.036916077;
shot.Intrinsics.PixelSizeMm[1]=0.036916077;
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();
double viewportYMm = shot.Intrinsics.PixelSizeMm[1]*shot.Intrinsics.ViewportPx[1];
float defaultFov=60.0;
shot.Intrinsics.FocalMm = viewportYMm/(2*tanf(vcg::math::ToRad(defaultFov/2))); //27.846098mm
shot.Extrinsics.SetIdentity();
}
bool GLArea::viewFromFile()
{
Shot shot;
QString filename = QFileDialog::getOpenFileName(this, tr("Load Project"), "./", tr("Xml Files (*.xml)"));
QFile qf(filename);
QFileInfo qfInfo(filename);
if( !qf.open(QIODevice::ReadOnly ) )
return false;
QString project_path = qfInfo.absoluteFilePath();
QDomDocument doc("XmlDocument"); //It represents the XML document
if(!doc.setContent( &qf ))
return false;
QString type = doc.doctype().name();
//TextAlign file project
if(type == "RegProjectML")
loadShotFromTextAlignFile(shot, doc);
//View State file
else if(type == "ViewState")
loadViewFromViewStateFile(shot, doc);
qDebug("End file reading");
qf.close();
return true;
}
void GLArea::loadShotFromTextAlignFile(Shot &shot, QDomDocument &doc)
{
QDomElement root = doc.documentElement();
QDomNode node;
node = root.firstChild();
//Devices
while(!node.isNull()){
if(QString::compare(node.nodeName(),"Device")==0)
{
QString type = node.attributes().namedItem("type").nodeValue();
if (type== "GlImageWidget")
{
//Aligned Image
if(QString::compare(node.attributes().namedItem("aligned").nodeValue(),"1")==0){
QDomNode nodeb = node.firstChild();
QDomNamedNodeMap attr = nodeb.attributes();
vcg::Point3d tra;
tra[0] = attr.namedItem("SimTra").nodeValue().section(' ',0,0).toDouble();
tra[1] = attr.namedItem("SimTra").nodeValue().section(' ',1,1).toDouble();
tra[2] = attr.namedItem("SimTra").nodeValue().section(' ',2,2).toDouble();
shot.Extrinsics.SetTra(-tra);
vcg::Matrix44d rot;
QStringList values = attr.namedItem("SimRot").nodeValue().split(" ", QString::SkipEmptyParts);
for(int y = 0; y < 4; y++)
for(int x = 0; x < 4; x++)
rot[y][x] = values[x + 4*y].toDouble();
shot.Extrinsics.SetRot(rot);
vcg::Camera<double> &cam = shot.Intrinsics;
cam.FocalMm = attr.namedItem("Focal").nodeValue().toDouble();
cam.ViewportPx.X() = attr.namedItem("Viewport").nodeValue().section(' ',0,0).toInt();
cam.ViewportPx.Y() = attr.namedItem("Viewport").nodeValue().section(' ',1,1).toInt();
cam.CenterPx[0] = attr.namedItem("Center").nodeValue().section(' ',0,0).toInt();
cam.CenterPx[1] = attr.namedItem("Center").nodeValue().section(' ',1,1).toInt();
cam.PixelSizeMm[0] = attr.namedItem("ScaleF").nodeValue().section(' ',0,0).toDouble();
cam.PixelSizeMm[1] = attr.namedItem("ScaleF").nodeValue().section(' ',1,1).toDouble();
cam.k[0] = attr.namedItem("LensDist").nodeValue().section(' ',0,0).toDouble();
cam.k[1] = attr.namedItem("LensDist").nodeValue().section(' ',1,1).toDouble();
// scale correction
float scorr = attr.namedItem("ScaleCorr").nodeValue().toDouble();
if(scorr != 0.0) {
cam.PixelSizeMm[0] *= scorr;
cam.PixelSizeMm[1] *= scorr;
}
}
}
}
node = node.nextSibling();
}
//Adjust params for Meshlab settings
//resize viewport
int w = shot.Intrinsics.ViewportPx[0];
int h = shot.Intrinsics.ViewportPx[1];
shot.Intrinsics.DistorCenterPx[0]=w/2;
shot.Intrinsics.DistorCenterPx[1]=h/2;
shot.Intrinsics.CenterPx[0]=w/2;
shot.Intrinsics.CenterPx[1]=h/2;
shot.Intrinsics.ViewportPx[0]=w;
shot.Intrinsics.ViewportPx[1]=h;
//Compute new scale
double viewportYMm=shot.Intrinsics.PixelSizeMm[1]*shot.Intrinsics.ViewportPx[1];
fov = 2*(vcg::math::ToDeg(atanf(viewportYMm/(2*shot.Intrinsics.FocalMm))));
float cameraDist = getCameraDistance();
Matrix44f rotFrom;
shot.Extrinsics.Rot().ToMatrix(rotFrom);
Point3f p1 = rotFrom*(vcg::Point3f::Construct(shot.Extrinsics.Tra()));
Point3f p2 = (Point3f(0,0,cameraDist));
trackball.track.sca =abs(p2.Z()/p1.Z());
loadShot(QPair<Shot, float> (shot,trackball.track.sca));
}
void GLArea::loadViewFromViewStateFile(Shot &shot, QDomDocument &doc)
{
QDomElement root = doc.documentElement();
QDomNode node = root.firstChild();
while(!node.isNull()){
if(QString::compare(node.nodeName(),"CamParam")==0)
{
QDomNamedNodeMap attr = node.attributes();
vcg::Point3d tra;
tra[0] = attr.namedItem("SimTra").nodeValue().section(' ',0,0).toDouble();
tra[1] = attr.namedItem("SimTra").nodeValue().section(' ',1,1).toDouble();
tra[2] = attr.namedItem("SimTra").nodeValue().section(' ',2,2).toDouble();
shot.Extrinsics.SetTra(-tra);
vcg::Matrix44d rot;
QStringList values = attr.namedItem("SimRot").nodeValue().split(" ", QString::SkipEmptyParts);
for(int y = 0; y < 4; y++)
for(int x = 0; x < 4; x++)
rot[y][x] = values[x + 4*y].toDouble();
shot.Extrinsics.SetRot(rot);
vcg::Camera<double> &cam = shot.Intrinsics;
cam.FocalMm = attr.namedItem("Focal").nodeValue().toDouble();
cam.ViewportPx.X() = attr.namedItem("Viewport").nodeValue().section(' ',0,0).toInt();
cam.ViewportPx.Y() = attr.namedItem("Viewport").nodeValue().section(' ',1,1).toInt();
cam.CenterPx[0] = attr.namedItem("Center").nodeValue().section(' ',0,0).toInt();
cam.CenterPx[1] = attr.namedItem("Center").nodeValue().section(' ',1,1).toInt();
cam.PixelSizeMm[0] = attr.namedItem("ScaleF").nodeValue().section(' ',0,0).toDouble();
cam.PixelSizeMm[1] = attr.namedItem("ScaleF").nodeValue().section(' ',1,1).toDouble();
cam.k[0] = attr.namedItem("LensDist").nodeValue().section(' ',0,0).toDouble();
cam.k[1] = attr.namedItem("LensDist").nodeValue().section(' ',1,1).toDouble();
// scale correction
float scorr = attr.namedItem("ScaleCorr").nodeValue().toDouble();
if(scorr != 0.0) {
cam.PixelSizeMm[0] *= scorr;
cam.PixelSizeMm[1] *= scorr;
}
}
else if (QString::compare(node.nodeName(),"ViewSettings")==0)
{
QDomNamedNodeMap attr = node.attributes();
trackball.track.sca = attr.namedItem("TrackScale").nodeValue().section(' ',0,0).toFloat();
nearPlane = attr.namedItem("NearPlane").nodeValue().section(' ',0,0).toFloat();
farPlane = attr.namedItem("FarPlane").nodeValue().section(' ',0,0).toFloat();
}
else if (QString::compare(node.nodeName(),"Render")==0)
{
QDomNamedNodeMap attr = node.attributes();
rm.drawMode = (vcg::GLW::DrawMode) (attr.namedItem("DrawMode").nodeValue().section(' ',0,0).toInt());
rm.colorMode = (vcg::GLW::ColorMode) (attr.namedItem("ColorMode").nodeValue().section(' ',0,0).toInt());
rm.textureMode = (vcg::GLW::TextureMode) (attr.namedItem("TextureMode").nodeValue().section(' ',0,0).toInt());
rm.lighting = (attr.namedItem("Lighting").nodeValue().section(' ',0,0).toInt() != 0);
rm.backFaceCull = (attr.namedItem("BackFaceCull").nodeValue().section(' ',0,0).toInt() != 0);
rm.doubleSideLighting = (attr.namedItem("DoubleSideLighting").nodeValue().section(' ',0,0).toInt() != 0);
rm.fancyLighting = (attr.namedItem("FancyLighting").nodeValue().section(' ',0,0).toInt() != 0);
rm.selectedFace = (attr.namedItem("SelectedFace").nodeValue().section(' ',0,0).toInt() != 0);
rm.selectedVert = (attr.namedItem("SelectedVert").nodeValue().section(' ',0,0).toInt() != 0);
}
node = node.nextSibling();
}
loadShot(QPair<Shot, float> (shot,trackball.track.sca));
}
void GLArea::viewToClipboard()
{
QClipboard *clipboard = QApplication::clipboard();
Shot shot = shotFromTrackball().first;
QDomDocument doc("ViewState");
QDomElement root = doc.createElement("project");
doc.appendChild( root );
QDomElement shotElem = doc.createElement( "CamParam" );
vcg::Point3d tra = -(shot.Extrinsics.Tra());
QString str = QString("%1 %2 %3 1").arg(tra[0]).arg(tra[1]).arg(tra[2]);
shotElem.setAttribute("SimTra", str);
vcg::Matrix44d rot = shot.Extrinsics.Rot();
str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 ")
.arg(rot[0][0]).arg(rot[0][1])
.arg(rot[0][2]).arg(rot[0][3])
.arg(rot[1][0]).arg(rot[1][1])
.arg(rot[1][2]).arg(rot[1][3])
.arg(rot[2][0]).arg(rot[2][1])
.arg(rot[2][2]).arg(rot[2][3])
.arg(rot[3][0]).arg(rot[3][1])
.arg(rot[3][2]).arg(rot[3][3]);
shotElem.setAttribute( "SimRot", str);
vcg::Camera<double> &cam = shot.Intrinsics;
shotElem.setAttribute( "Focal", cam.FocalMm);
str = QString("%1 %2").arg(cam.k[0]).arg(cam.k[1]);
shotElem.setAttribute( "LensDist", str);
str = QString("%1 %2").arg(cam.PixelSizeMm[0]).arg(cam.PixelSizeMm[1]);
shotElem.setAttribute( "ScaleF", str);
str = QString("%1 %2").arg(cam.ViewportPx[0]).arg(cam.ViewportPx[1]);
shotElem.setAttribute( "Viewport", str);
str = QString("%1 %2").arg((int)(cam.DistorCenterPx[0])).arg((int)(cam.DistorCenterPx[1]));
shotElem.setAttribute( "Center", str);
str = QString("%1").arg((double) 1);
shotElem.setAttribute( "ScaleCorr", str);
root.appendChild(shotElem);
QDomElement settingsElem = doc.createElement( "ViewSettings" );
settingsElem.setAttribute( "TrackScale", trackball.track.sca);
settingsElem.setAttribute( "NearPlane", nearPlane);
settingsElem.setAttribute( "FarPlane", farPlane);
root.appendChild(settingsElem);
QDomElement renderElem = doc.createElement( "Render");
renderElem.setAttribute("DrawMode",rm.drawMode);
renderElem.setAttribute("ColorMode",rm.colorMode);
renderElem.setAttribute("TextureMode",rm.textureMode);
renderElem.setAttribute("Lighting",rm.lighting);
renderElem.setAttribute("BackFaceCull",rm.backFaceCull);
renderElem.setAttribute("DoubleSideLighting",rm.doubleSideLighting);
renderElem.setAttribute("FancyLighting",rm.fancyLighting);
renderElem.setAttribute("SelectedFace",rm.selectedFace);
renderElem.setAttribute("SelectedVert",rm.selectedVert);
root.appendChild(renderElem);
clipboard->setText(doc.toString()); //.remove(QChar('\n')));
}
void GLArea::viewFromClipboard()
{
QClipboard *clipboard = QApplication::clipboard();
QString shotString = clipboard->text();
Shot shot;
QDomDocument doc("StringDoc");
doc.setContent(shotString);
loadViewFromViewStateFile(shot, doc);
}
QPair<vcg::Shot<double>,float> GLArea::shotFromTrackball()
{
Shot shot;
initializeShot(shot);
double viewportYMm=shot.Intrinsics.PixelSizeMm[1]*shot.Intrinsics.ViewportPx[1];
shot.Intrinsics.FocalMm = viewportYMm/(2*tanf(vcg::math::ToRad(fov/2)));
float cameraDist = getCameraDistance();
//add the translation introduced by gluLookAt() (0,0,cameraDist)---------------------------------------
//T(gl)*S*R*T(t) => SR(gl+t) => S R (S^(-1)R^(-1)gl + t)
//Add translation S^(-1) R^(-1)(gl)
//Shot doesn't introduce scaling
//---------------------------------------------------------------------
shot.Extrinsics.SetTra( shot.Extrinsics.Tra() + (Inverse(shot.Extrinsics.Rot())*Point3d(0, 0, cameraDist)));
Shot newShot = track2ShotCPU(shot, &trackball);
////Expressing scaling as a translation along z
////k is the ratio between default scale and new scale
//double oldScale= 3.0f/meshDoc->bbox().Diag();
//double k= oldScale/trackball.track.sca;
////Apply this formula
//// R(t+p) = kR'(t'+p) forall p, R=R', k is a costant
//// R(t)= kR(t')
//// t = k*t'
//Point3d t1 = newShot.Extrinsics.Tra();
//
//Matrix44d rapM = Matrix44d().SetScale(k, k, k);
//Point3d t0 = rapM*t1;
//newShot.Extrinsics.SetTra(t0);
return QPair<Shot, float> (newShot,trackball.track.sca);
}
void GLArea::loadShot(const QPair<vcg::Shot<double>,float> &shotAndScale){
Shot shot = shotAndScale.first;
double viewportYMm=shot.Intrinsics.PixelSizeMm[1]*shot.Intrinsics.ViewportPx[1];
fov = 2*(vcg::math::ToDeg(atanf(viewportYMm/(2*shot.Intrinsics.FocalMm))));
float cameraDist = getCameraDistance();
//reset trackball. The point of view must be set only by the shot
trackball.Reset();
trackball.track.sca = shotAndScale.second;
/*Point3f point = meshDoc->bbox().Center();
Point3f p1 = ((trackball.track.Matrix()*(point-trackball.center))- Point3f(0,0,cameraDist));*/
shot2Track(shot, cameraDist,trackball);
//Expressing the translation along Z with a scale factor k
//Point3f p2 = ((trackball.track.Matrix()*(point-trackball.center))- Point3f(0,0,cameraDist));
////k is the ratio between the distances along z of two correspondent points (before and after the traslazion)
////from the point of view
//float k= abs(p2.Z()/p1.Z());
//float sca= trackball.track.sca/k;
//Point3f tra = trackball.track.tra;
//
//// Apply this formula:
//// SR(t+p) -v = k[S'R'(t'+p) -v] forall p, R=R', k is a costant
//// SR(t) -v = k[S'R(t') -v]
//// t' = 1/k* S'^-1St + (k-1)/k S'^-1*R^-1v
//Matrix44f s0 = Matrix44f().SetScale(trackball.track.sca,trackball.track.sca, trackball.track.sca);
//Matrix44f s1 = Matrix44f().SetScale(sca, sca, sca);
//Matrix44f r;
//trackball.track.rot.ToMatrix(r);
//Matrix44f rapM = Matrix44f().SetScale(1/k, 1/k, 1/k);
//Matrix44f rapM2 = Matrix44f().SetScale(1-1/k, 1-1/k, 1-1/k);
//Point3f t1 = rapM*Inverse(s1)*s0*tra + rapM2*Inverse(s1)*Inverse(r)*Point3f(0,0,cameraDist);
//trackball.track.sca =sca;
//trackball.track.tra =t1 /*+ tb.track.rot.Inverse().Rotate(glLookAt)*/ ;
update();
}
void GLArea::createOrthoView(QString dir)
{
Shot view;
initializeShot(view);
fov =5;
double viewportYMm = view.Intrinsics.PixelSizeMm[1]*view.Intrinsics.ViewportPx[1];
view.Intrinsics.FocalMm = viewportYMm/(2*tanf(vcg::math::ToRad(fov/2))); //27.846098 equivalente a circa 60 gradi
trackball.Reset();
float newScale= 3.0f/meshDoc->bbox().Diag();
trackball.track.sca = newScale;
trackball.track.tra = -meshDoc->bbox().Center();
vcg::Matrix44d rot;
if(dir == tr("Top"))
rot.SetRotateDeg(90,Point3<double>(1,0,0));
else if(dir == tr("Bottom"))
rot.SetRotateDeg(90,Point3<double>(-1,0,0));
else if(dir == tr("Left"))
rot.SetRotateDeg(90,Point3<double>(0,1,0));
else if(dir == tr("Right"))
rot.SetRotateDeg(90,Point3<double>(0,-1,0));
else if(dir == tr("Front"))
rot.SetRotateDeg(0,Point3<double>(0,1,0));
else if(dir == tr("Back"))
rot.SetRotateDeg(180,Point3<double>(0,1,0));
view.Extrinsics.SetRot(rot);
float cameraDist = getCameraDistance();
//add the translation introduced by gluLookAt() (0,0,cameraDist)---------------------------------------
//T(gl)*S*R*T(t) => SR(gl+t) => S R (S^(-1)R^(-1)gl + t)
//Add translation S^(-1) R^(-1)(gl)
//Shot doesn't introduce scaling
//---------------------------------------------------------------------
view.Extrinsics.SetTra( view.Extrinsics.Tra() + (Inverse(view.Extrinsics.Rot())*Point3d(0, 0, cameraDist)));
Shot shot = track2ShotCPU(view, &trackball);
QPair<Shot,float> shotAndScale = QPair<Shot,float> (shot, trackball.track.sca);
loadShot(shotAndScale);
}

View File

@ -34,6 +34,8 @@
#include <wrap/gl/math.h>
#include <wrap/gl/trimesh.h>
#include <wrap/gui/trackball.h>
#include <vcg/math/shot.h>
#include <wrap/gl/shot.h>
#include "../common/interfaces.h"
#include "../common/filterscript.h"
@ -69,6 +71,8 @@ class GLArea : public Viewer
{
Q_OBJECT
typedef vcg::Shot<double> Shot;
public:
GLArea(MultiViewer_Container *mvcont, RichParameterSet *current);
~GLArea();
@ -83,7 +87,7 @@ public:
vcg::Trackball trackball;
vcg::Trackball trackball_light;
GLLogStream *log;
GLLogStream *log;
FilterScript filterHistory;
GLAreaSetting glas;
QSize curSiz;
@ -302,7 +306,7 @@ private:
float cfps;
float lastTime;
QImage snapBuffer;
QImage snapBuffer;
bool takeSnapTile;
enum AnimMode { AnimNone, AnimSpin, AnimInterp};
@ -310,8 +314,132 @@ private:
int tileCol, tileRow, totalCols, totalRows;
void setCursorTrack(vcg::TrackMode *tm);
//-----------Shot support----------------------------
public:
QPair<Shot, float > shotFromTrackball();
bool viewFromFile();
void createOrthoView(QString);
void viewToClipboard();
void viewFromClipboard();
void loadShot(const QPair<Shot, float> &) ;
private:
float getCameraDistance();
void initializeShot(Shot &shot);
void loadShotFromTextAlignFile(Shot &shot, QDomDocument &doc);
void loadViewFromViewStateFile(Shot &shot, QDomDocument &doc);
/*
Given a shot "refCamera" and a trackball "track", computes a new shot which is equivalent
to apply "refCamera" o "track" (via GPU).
*/
template <class T>
vcg::Shot<T> track2ShotGPU(vcg::Shot<T> &refCamera, vcg::Trackball *track){
vcg::Shot<T> view;
double _near, _far;
_near = 0.1;
_far = 100;
//get OpenGL modelview matrix after applying the trackball
GlShot<vcg::Shot<T> >::SetView(refCamera, _near, _far);
glPushMatrix();
track->GetView();
track->Apply();
vcg::Matrix44d model;
glGetv(GL_MODELVIEW_MATRIX, model);
glPopMatrix();
GlShot<vcg::Shot<T> >::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<T>::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" (via CPU).
*/
template <class T>
vcg::Shot<T> track2ShotCPU(vcg::Shot<T> &refCamera, vcg::Trackball *track){
vcg::Shot<T> view;
double _near, _far;
_near = 0.1;
_far = 100;
//get shot extrinsics matrix
vcg::Matrix44f shotExtr;
refCamera.GetWorldToExtrinsicsMatrix().ToMatrix(shotExtr);
vcg::Matrix44f model2;
model2 = (shotExtr)* track->Matrix();
vcg::Matrix44d model;
model2.ToMatrix(model);
//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<T>::Construct(tra));
//use same current intrinsics
view.Intrinsics = refCamera.Intrinsics;
return view;
}
/*
TBD
*/
template <class T>
void shot2Track(const vcg::Shot<T> &from, const float cameraDist, vcg::Trackball &tb){
vcg::Quaterniond qfrom; qfrom.FromMatrix(from.Extrinsics.Rot());
tb.track.rot = vcg::Quaternionf::Construct(qfrom);
tb.track.tra = (vcg::Point3f::Construct(-from.Extrinsics.Tra()));
tb.track.tra += vcg::Point3f::Construct(tb.track.rot.Inverse().Rotate(Point3f(0,0,cameraDist)))*(1/tb.track.sca);
}
};
#endif

View File

@ -109,8 +109,9 @@ void MainWindow::updateWindowMenu()
windowsMenu->addSeparator();
// Split/Unsplit SUBmenu
if((mdiarea-> subWindowList().size()>0)){
// Split/Unsplit SUBmenu
splitModeMenu = windowsMenu->addMenu(tr("&Split current view"));
splitModeMenu->addAction(setSplitHAct);
@ -118,6 +119,26 @@ void MainWindow::updateWindowMenu()
windowsMenu->addAction(setUnsplitAct);
// Link act
windowsMenu->addAction(linkViewersAct);
// View From SUBmenu
viewFromMenu = windowsMenu->addMenu(tr("&View from"));
viewFromMenu->addAction(viewTopAct);
viewFromMenu->addAction(viewBottomAct);
viewFromMenu->addAction(viewLeftAct);
viewFromMenu->addAction(viewRightAct);
viewFromMenu->addAction(viewFrontAct);
viewFromMenu->addAction(viewBackAct);
// View From File act
windowsMenu->addAction(viewFromFileAct);
// Copy and paste shot acts
windowsMenu->addAction(copyShotToClipboardAct);
windowsMenu->addAction(pasteShotFromClipboardAct);
MultiViewer_Container *mvc = currentDocContainer();
if(mvc)
{
@ -127,6 +148,10 @@ void MainWindow::updateWindowMenu()
setSplitHAct->setEnabled(current->size().height()/2 > current->minimumSizeHint().height());
setSplitVAct->setEnabled(current->size().width()/2 > current->minimumSizeHint().width());
linkViewersAct->setEnabled(currentDocContainer()->viewerCounter()>1);
if(currentDocContainer()->viewerCounter()==1)
linkViewersAct->setChecked(false);
windowsMenu->addSeparator();
}
}
@ -452,6 +477,38 @@ void MainWindow::unsplitFromHandle(QAction * qa)
setUnsplit();
}
void MainWindow::linkViewers()
{
MultiViewer_Container *mvc = currentDocContainer();
mvc->updateTrackballInViewers();
}
void MainWindow::viewFrom(QAction *qa)
{
MultiViewer_Container *mvc = currentDocContainer();
((GLArea*)mvc->currentView())->createOrthoView(qa->text());
}
void MainWindow::readViewFromFile()
{
MultiViewer_Container *mvc = currentDocContainer();
((GLArea*)mvc->currentView())->viewFromFile();
updateMenus();
}
void MainWindow::copyViewToClipBoard()
{
MultiViewer_Container *mvc = currentDocContainer();
((GLArea*)mvc->currentView())->viewToClipboard();
}
void MainWindow::pasteViewFromClipboard()
{
MultiViewer_Container *mvc = currentDocContainer();
((GLArea*)mvc->currentView())->viewFromClipboard();
updateMenus();
}
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
//qDebug("dragEnterEvent: %s",event->format());

View File

@ -288,3 +288,12 @@ void MultiViewer_Container::updateAll(){
void MultiViewer_Container::update(int id){
getViewer(id)->update();
}
void MultiViewer_Container::updateTrackballInViewers()
{
QPair<Shot,float> shotAndScale = ((GLArea*)currentView())->shotFromTrackball();
foreach(Viewer* viewer, viewerList)
if(viewer->getId() != currentId){
((GLArea*) viewer)->loadShot(shotAndScale);
}
}

View File

@ -66,7 +66,7 @@ class MultiViewer_Container : public Splitter
{
Q_OBJECT
/*typedef vcg::Shot<double> Shot;*/
typedef vcg::Shot<double> Shot;
public:
MultiViewer_Container(QWidget *parent);
@ -85,6 +85,8 @@ public:
Viewer* getViewer(int id);
int getViewerByPicking(QPoint);
void updateTrackballInViewers();
MeshDocument meshDoc;
int currentId;