25 #include "qglviewer.h"
26 #include "manipulatedCameraFrame.h"
29 using namespace qglviewer;
39 : frame_(NULL), fieldOfView_(M_PI/4.0f), modelViewMatrixIsUpToDate_(false), projectionMatrixIsUpToDate_(false)
73 for (
unsigned short j=0; j<16; ++j)
75 modelViewMatrix_[j] = ((j%5 == 0) ? 1.0 : 0.0);
77 projectionMatrix_[j] = 0.0;
89 delete interpolationKfi_;
95 : QObject(), frame_(NULL)
102 for (
unsigned short j=0; j<16; ++j)
104 modelViewMatrix_[j] = ((j%5 == 0) ? 1.0 : 0.0);
106 projectionMatrix_[j] = 0.0;
139 orthoCoef_ = camera.orthoCoef_;
140 projectionMatrixIsUpToDate_ =
false;
169 screenWidth_ = width > 0 ? width : 1;
170 screenHeight_ = height > 0 ? height : 1;
171 projectionMatrixIsUpToDate_ =
false;
221 case Camera::PERSPECTIVE : z = zMin;
break;
222 case Camera::ORTHOGRAPHIC : z = 0.0;
break;
248 projectionMatrixIsUpToDate_ =
false;
266 if ( (type == Camera::ORTHOGRAPHIC) && (type_ == Camera::PERSPECTIVE) )
269 projectionMatrixIsUpToDate_ =
false;
291 disconnect(frame_, SIGNAL(modified()),
this, SLOT(onFrameModified()));
297 connect(frame_, SIGNAL(modified()),
this, SLOT(onFrameModified()));
352 if (projectionMatrixIsUpToDate_)
return;
354 const float ZNear =
zNear();
355 const float ZFar =
zFar();
359 case Camera::PERSPECTIVE:
364 projectionMatrix_[5] = f;
365 projectionMatrix_[10] = (ZNear + ZFar) / (ZNear - ZFar);
366 projectionMatrix_[11] = -1.0;
367 projectionMatrix_[14] = 2.0 * ZNear * ZFar / (ZNear - ZFar);
368 projectionMatrix_[15] = 0.0;
372 case Camera::ORTHOGRAPHIC:
376 projectionMatrix_[0] = 1.0/w;
377 projectionMatrix_[5] = 1.0/h;
378 projectionMatrix_[10] = -2.0/(ZFar - ZNear);
379 projectionMatrix_[11] = 0.0;
380 projectionMatrix_[14] = -(ZFar + ZNear)/(ZFar - ZNear);
381 projectionMatrix_[15] = 1.0;
387 projectionMatrixIsUpToDate_ =
true;
402 if (modelViewMatrixIsUpToDate_)
return;
406 const double q00 = 2.0l * q[0] * q[0];
407 const double q11 = 2.0l * q[1] * q[1];
408 const double q22 = 2.0l * q[2] * q[2];
410 const double q01 = 2.0l * q[0] * q[1];
411 const double q02 = 2.0l * q[0] * q[2];
412 const double q03 = 2.0l * q[0] * q[3];
414 const double q12 = 2.0l * q[1] * q[2];
415 const double q13 = 2.0l * q[1] * q[3];
417 const double q23 = 2.0l * q[2] * q[3];
419 modelViewMatrix_[0] = 1.0l - q11 - q22;
420 modelViewMatrix_[1] = q01 - q23;
421 modelViewMatrix_[2] = q02 + q13;
422 modelViewMatrix_[3] = 0.0l;
424 modelViewMatrix_[4] = q01 + q23;
425 modelViewMatrix_[5] = 1.0l - q22 - q00;
426 modelViewMatrix_[6] = q12 - q03;
427 modelViewMatrix_[7] = 0.0l;
429 modelViewMatrix_[8] = q02 - q13;
430 modelViewMatrix_[9] = q12 + q03;
431 modelViewMatrix_[10] = 1.0l - q11 - q00;
432 modelViewMatrix_[11] = 0.0l;
436 modelViewMatrix_[12] = -t.x;
437 modelViewMatrix_[13] = -t.y;
438 modelViewMatrix_[14] = -t.z;
439 modelViewMatrix_[15] = 1.0l;
441 modelViewMatrixIsUpToDate_ =
true;
466 glMatrixMode(GL_PROJECTION);
473 glMultMatrixd(projectionMatrix_);
503 glMatrixMode(GL_MODELVIEW);
506 glLoadMatrixd(modelViewMatrix_);
508 glMultMatrixd(modelViewMatrix_);
538 float left, right, bottom, top;
539 float screenHalfWidth, halfWidth, side, shift, delta;
541 glMatrixMode(GL_PROJECTION);
546 case Camera::PERSPECTIVE:
558 side = leftBuffer ? -1.0 : 1.0;
560 left = -halfWidth + side * delta;
561 right = halfWidth + side * delta;
564 glFrustum(left, right, bottom, top,
zNear(),
zFar() );
567 case Camera::ORTHOGRAPHIC:
568 qWarning(
"Camera::setProjectionMatrixStereo: Stereo not available with Ortho mode");
594 glMatrixMode(GL_MODELVIEW);
601 modelViewMatrix_[12] -= shift;
603 modelViewMatrix_[12] += shift;
604 glLoadMatrixd(modelViewMatrix_);
624 for (
unsigned short i=0; i<16; ++i)
625 m[i] = projectionMatrix_[i];
631 static GLdouble mat[16];
633 for (
unsigned short i=0; i<16; ++i)
634 m[i] =
float(mat[i]);
656 for (
unsigned short i=0; i<16; ++i)
657 m[i] = modelViewMatrix_[i];
664 static GLdouble mat[16];
666 for (
unsigned short i=0; i<16; ++i)
667 m[i] =
float(mat[i]);
680 for (
unsigned short i=0; i<4; ++i)
682 for (
unsigned short j=0; j<4; ++j)
685 for (
unsigned short k=0; k<4; ++k)
686 sum += proj[i+4*k]*mv[k+4*j];
695 static GLdouble mat[16];
697 for (
unsigned short i=0; i<16; ++i)
698 m[i] =
float(mat[i]);
709 qWarning(
"Scene radius must be positive - Ignoring value");
713 sceneRadius_ = radius;
714 projectionMatrixIsUpToDate_ =
false;
735 sceneCenter_ = center;
737 projectionMatrixIsUpToDate_ =
false;
755 void Camera::setRevolveAroundPoint(
const Vec& point) {
756 qWarning(
"setRevolveAroundPoint() is deprecated, use setPivotPoint() instead");
759 bool Camera::setRevolveAroundPointFromPixel(
const QPoint& pixel) {
760 qWarning(
"setRevolveAroundPointFromPixel() is deprecated, use setPivotPointFromPixel() instead");
763 Vec Camera::revolveAroundPoint()
const {
764 qWarning(
"revolveAroundPoint() is deprecated, use pivotPoint() instead");
782 if ((prevDist > 1E-9) && (newDist > 1E-9))
783 orthoCoef_ *= prevDist / newDist;
784 projectionMatrixIsUpToDate_ =
false;
823 case Camera::PERSPECTIVE :
825 case Camera::ORTHOGRAPHIC :
877 const float coef = 0.1f;
975 glReadPixels(pixel.x(),
screenHeight()-1-pixel.y(), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
977 Vec point(pixel.x(), pixel.y(), depth);
1022 float distance = 0.0f;
1025 case Camera::PERSPECTIVE :
1027 const float yview = radius / sin(
fieldOfView() / 2.0);
1029 distance = qMax(xview, yview);
1032 case Camera::ORTHOGRAPHIC :
1046 float diameter = qMax(fabs(max[1]-min[1]), fabs(max[0]-min[0]));
1047 diameter = qMax(fabsf(max[2]-min[2]), diameter);
1062 const QPoint center = rectangle.center();
1066 Vec newCenter = orig + distToPlane / (dir*vd) * dir;
1069 const Vec pointX = orig + distToPlane / (dir*vd) * dir;
1072 const Vec pointY = orig + distToPlane / (dir*vd) * dir;
1074 float distance = 0.0f;
1077 case Camera::PERSPECTIVE :
1080 const float distY = (pointY-newCenter).norm() / sin(
fieldOfView()/2.0);
1081 distance = qMax(distX, distY);
1084 case Camera::ORTHOGRAPHIC :
1086 const float dist = ((newCenter-
pivotPoint()) * vd);
1088 const float distX = (pointX-newCenter).norm() / orthoCoef_ / ((
aspectRatio() < 1.0) ? 1.0 :
aspectRatio());
1089 const float distY = (pointY-newCenter).norm() / orthoCoef_ / ((
aspectRatio() < 1.0) ? 1.0/
aspectRatio() : 1.0);
1090 distance = dist + qMax(distX, distY);
1095 Vec newPos(newCenter - distance * vd);
1126 frame()->updateSceneUpVector();
1142 Vec axis(0.0, 1.0, 0.0);
1144 axis =
Vec(-cos(theta), 0., sin(theta));
1153 frame()->updateSceneUpVector();
1180 static float det(
float m00,
float m01,
float m02,
1181 float m10,
float m11,
float m12,
1182 float m20,
float m21,
float m22)
1184 return m00*m11*m22 + m01*m12*m20 + m02*m10*m21 - m20*m11*m02 - m10*m01*m22 - m00*m21*m12;
1188 static inline unsigned int ind(
unsigned int i,
unsigned int j)
1297 double upperLeft[3][3];
1298 for (
int i=0; i<3; ++i)
1299 for (
int j=0; j<3; ++j)
1300 upperLeft[i][j] = modelViewMatrix[i*4+j];
1304 q.setFromRotationMatrix(upperLeft);
1336 Vec line_0(matrix[ind(0,0)],matrix[ind(0,1)],matrix[ind(0,2)]);
1337 Vec line_1(matrix[ind(1,0)],matrix[ind(1,1)],matrix[ind(1,2)]);
1338 Vec line_2(matrix[ind(2,0)],matrix[ind(2,1)],matrix[ind(2,2)]);
1353 const Vec cam_pos =
Vec(det(matrix[ind(0,1)],matrix[ind(0,2)],matrix[ind(0,3)],
1354 matrix[ind(1,1)],matrix[ind(1,2)],matrix[ind(1,3)],
1355 matrix[ind(2,1)],matrix[ind(2,2)],matrix[ind(2,3)]),
1357 -det(matrix[ind(0,0)],matrix[ind(0,2)],matrix[ind(0,3)],
1358 matrix[ind(1,0)],matrix[ind(1,2)],matrix[ind(1,3)],
1359 matrix[ind(2,0)],matrix[ind(2,2)],matrix[ind(2,3)]),
1361 det(matrix[ind(0,0)],matrix[ind(0,1)],matrix[ind(0,3)],
1362 matrix[ind(1,0)],matrix[ind(1,1)],matrix[ind(1,3)],
1363 matrix[ind(2,0)],matrix[ind(2,1)],matrix[ind(2,3)])) /
1365 (-det(matrix[ind(0,0)],matrix[ind(0,1)],matrix[ind(0,2)],
1366 matrix[ind(1,0)],matrix[ind(1,1)],matrix[ind(1,2)],
1367 matrix[ind(2,0)],matrix[ind(2,1)],matrix[ind(2,2)]));
1372 Vec column_2 = -line_2;
1375 Vec column_0 = ((column_2^line_0)^column_2);
1380 Vec column_1 = -((column_2^line_1)^column_2);
1384 rot[0][0] = column_0[0];
1385 rot[1][0] = column_0[1];
1386 rot[2][0] = column_0[2];
1388 rot[0][1] = column_1[0];
1389 rot[1][1] = column_1[1];
1390 rot[2][1] = column_1[2];
1392 rot[0][2] = column_2[0];
1393 rot[1][2] = column_2[1];
1394 rot[2][2] = column_2[2];
1404 Vec dummy = line_1^column_0;
1406 float fov = acos(column_2*dummy) * 2.0;
1410 q.setFromRotationMatrix(rot);
1485 for (
int i=0; i<3; ++i)
1493 for (
int i=0; i<3; ++i)
1587 static GLint viewport[4];
1593 gluProject(tmp.x,tmp.y,tmp.z, modelViewMatrix_, projectionMatrix_, viewport, &x,&y,&z);
1596 gluProject(src.x,src.y,src.z, modelViewMatrix_, projectionMatrix_, viewport, &x,&y,&z);
1634 static GLint viewport[4];
1636 gluUnProject(src.x,src.y,src.z, modelViewMatrix_, projectionMatrix_, viewport, &x,&y,&z);
1647 for (
int i=0; i<3; ++i)
1655 for (
int i=0; i<3; ++i)
1666 if (kfi_.contains(i))
1712 if (!kfi_.contains(i))
1715 kfi_[i]->addKeyFrame(*(
frame()));
1728 if (kfi_.contains(i)) {
1729 if (kfi_[i]->interpolationIsStarted())
1730 kfi_[i]->stopInterpolation();
1732 kfi_[i]->startInterpolation();
1743 if (kfi_.contains(i)) {
1744 if ((kfi_[i]->interpolationIsStarted()))
1745 kfi_[i]->stopInterpolation();
1748 kfi_[i]->resetInterpolation();
1749 kfi_[i]->interpolateAtTime(kfi_[i]->interpolationTime());
1764 if (kfi_.contains(i))
1766 kfi_[i]->stopInterpolation();
1780 for (QMap<int, KeyFrameInterpolator*>::ConstIterator it = kfi_.begin(), end=kfi_.end(); it != end; ++it)
1813 QDomElement de = document.createElement(name);
1814 QDomElement paramNode = document.createElement(
"Parameters");
1815 paramNode.setAttribute(
"fieldOfView", QString::number(
fieldOfView()));
1816 paramNode.setAttribute(
"zNearCoefficient", QString::number(
zNearCoefficient()));
1818 paramNode.setAttribute(
"orthoCoef", QString::number(orthoCoef_));
1819 paramNode.setAttribute(
"sceneRadius", QString::number(
sceneRadius()));
1824 case Camera::PERSPECTIVE : paramNode.setAttribute(
"Type",
"PERSPECTIVE");
break;
1825 case Camera::ORTHOGRAPHIC : paramNode.setAttribute(
"Type",
"ORTHOGRAPHIC");
break;
1827 de.appendChild(paramNode);
1829 QDomElement stereoNode = document.createElement(
"Stereo");
1830 stereoNode.setAttribute(
"IODist", QString::number(
IODistance()));
1831 stereoNode.setAttribute(
"focusDistance", QString::number(
focusDistance()));
1833 de.appendChild(stereoNode);
1835 de.appendChild(
frame()->
domElement(
"ManipulatedCameraFrame", document));
1838 for (QMap<int, KeyFrameInterpolator*>::ConstIterator it = kfi_.begin(), end=kfi_.end(); it != end; ++it)
1840 QDomElement kfNode = (it.value())->
domElement(
"KeyFrameInterpolator", document);
1841 kfNode.setAttribute(
"index", QString::number(it.key()));
1842 de.appendChild(kfNode);
1871 QDomElement child=element.firstChild().toElement();
1873 QMutableMapIterator<int, KeyFrameInterpolator*> it(kfi_);
1874 while (it.hasNext()) {
1879 while (!child.isNull())
1881 if (child.tagName() ==
"Parameters")
1884 setFieldOfView(DomUtils::floatFromDom(child,
"fieldOfView", M_PI/4.0f));
1887 orthoCoef_ = DomUtils::floatFromDom(child,
"orthoCoef", tan(
fieldOfView()/2.0));
1891 QString
type = child.attribute(
"Type",
"PERSPECTIVE");
1892 if (type ==
"PERSPECTIVE")
setType(Camera::PERSPECTIVE);
1893 if (type ==
"ORTHOGRAPHIC")
setType(Camera::ORTHOGRAPHIC);
1895 QDomElement child2=child.firstChild().toElement();
1896 while (!child2.isNull())
1900 if (child2.tagName() ==
"SceneCenter")
1903 child2 = child2.nextSibling().toElement();
1907 if (child.tagName() ==
"ManipulatedCameraFrame")
1910 if (child.tagName() ==
"Stereo")
1912 setIODistance(DomUtils::floatFromDom(child,
"IODist", 0.062f));
1917 if (child.tagName() ==
"KeyFrameInterpolator")
1919 int index = DomUtils::intFromDom(child,
"index", 0);
1925 child = child.nextSibling().toElement();
1944 case Camera::PERSPECTIVE:
1953 case Camera::ORTHOGRAPHIC:
1969 qWarning(
"drawCamera is deprecated. Use Camera::draw() instead.");
1996 glMultMatrixd(
frame()->worldMatrix());
2001 points[0].z = scale *
zNear();
2002 points[1].z = scale *
zFar();
2006 case Camera::PERSPECTIVE:
2008 points[0].y = points[0].z * tan(
fieldOfView()/2.0);
2011 const float ratio = points[1].z / points[0].z;
2013 points[1].y = ratio * points[0].y;
2014 points[1].x = ratio * points[0].x;
2017 case Camera::ORTHOGRAPHIC:
2021 points[0].x = points[1].x = scale * float(hw);
2022 points[0].y = points[1].y = scale * float(hh);
2027 const int farIndex = drawFarPlane?1:0;
2031 for (
int i=farIndex; i>=0; --i)
2033 glNormal3f(0.0, 0.0, (i==0)?1.0:-1.0);
2034 glVertex3f( points[i].x, points[i].y, -points[i].z);
2035 glVertex3f(-points[i].x, points[i].y, -points[i].z);
2036 glVertex3f(-points[i].x, -points[i].y, -points[i].z);
2037 glVertex3f( points[i].x, -points[i].y, -points[i].z);
2042 const float arrowHeight = 1.5f * points[0].y;
2043 const float baseHeight = 1.2f * points[0].y;
2044 const float arrowHalfWidth = 0.5f * points[0].x;
2045 const float baseHalfWidth = 0.3f * points[0].x;
2047 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2050 glVertex3f(-baseHalfWidth, points[0].y, -points[0].z);
2051 glVertex3f( baseHalfWidth, points[0].y, -points[0].z);
2052 glVertex3f( baseHalfWidth, baseHeight, -points[0].z);
2053 glVertex3f(-baseHalfWidth, baseHeight, -points[0].z);
2057 glBegin(GL_TRIANGLES);
2058 glVertex3f( 0.0f, arrowHeight, -points[0].z);
2059 glVertex3f(-arrowHalfWidth, baseHeight, -points[0].z);
2060 glVertex3f( arrowHalfWidth, baseHeight, -points[0].z);
2066 case Camera::PERSPECTIVE :
2068 glVertex3f(0.0f, 0.0f, 0.0f);
2069 glVertex3f( points[farIndex].x, points[farIndex].y, -points[farIndex].z);
2070 glVertex3f(0.0f, 0.0f, 0.0f);
2071 glVertex3f(-points[farIndex].x, points[farIndex].y, -points[farIndex].z);
2072 glVertex3f(0.0f, 0.0f, 0.0f);
2073 glVertex3f(-points[farIndex].x, -points[farIndex].y, -points[farIndex].z);
2074 glVertex3f(0.0f, 0.0f, 0.0f);
2075 glVertex3f( points[farIndex].x, -points[farIndex].y, -points[farIndex].z);
2078 case Camera::ORTHOGRAPHIC :
2082 glVertex3f( points[0].x, points[0].y, -points[0].z);
2083 glVertex3f( points[1].x, points[1].y, -points[1].z);
2084 glVertex3f(-points[0].x, points[0].y, -points[0].z);
2085 glVertex3f(-points[1].x, points[1].y, -points[1].z);
2086 glVertex3f(-points[0].x, -points[0].y, -points[0].z);
2087 glVertex3f(-points[1].x, -points[1].y, -points[1].z);
2088 glVertex3f( points[0].x, -points[0].y, -points[0].z);
2089 glVertex3f( points[1].x, -points[1].y, -points[1].z);
2128 const float posViewDir = pos * viewDir;
2130 static Vec normal[6];
2131 static GLdouble dist[6];
2135 case Camera::PERSPECTIVE :
2138 const float chhfov = cos(hhfov);
2139 const float shhfov = sin(hhfov);
2140 normal[0] = - shhfov * viewDir;
2141 normal[1] = normal[0] + chhfov * right;
2142 normal[0] = normal[0] - chhfov * right;
2144 normal[2] = -viewDir;
2145 normal[3] = viewDir;
2148 const float chfov = cos(hfov);
2149 const float shfov = sin(hfov);
2150 normal[4] = - shfov * viewDir;
2151 normal[5] = normal[4] - chfov * up;
2152 normal[4] = normal[4] + chfov * up;
2154 for (
int i=0; i<2; ++i)
2155 dist[i] = pos * normal[i];
2156 for (
int j=4; j<6; ++j)
2157 dist[j] = pos * normal[j];
2165 const float posRightCosHH = chhfov * pos * right;
2166 dist[0] = -shhfov * posViewDir;
2167 dist[1] = dist[0] + posRightCosHH;
2168 dist[0] = dist[0] - posRightCosHH;
2169 const float posUpCosH = chfov * pos * up;
2170 dist[4] = - shfov * posViewDir;
2171 dist[5] = dist[4] - posUpCosH;
2172 dist[4] = dist[4] + posUpCosH;
2176 case Camera::ORTHOGRAPHIC :
2184 dist[0] = (pos - hw * right) * normal[0];
2185 dist[1] = (pos + hw * right) * normal[1];
2186 dist[4] = (pos + hh * up) * normal[4];
2187 dist[5] = (pos - hh * up) * normal[5];
2192 normal[2] = -viewDir;
2193 normal[3] = viewDir;
2194 dist[2] = -posViewDir -
zNear();
2195 dist[3] = posViewDir +
zFar();
2197 for (
int i=0; i<6; ++i)
2199 coef[i][0] = GLdouble(normal[i].x);
2200 coef[i][1] = GLdouble(normal[i].y);
2201 coef[i][2] = GLdouble(normal[i].z);
2202 coef[i][3] = dist[i];
2206 void Camera::onFrameModified() {
2207 projectionMatrixIsUpToDate_ =
false;
2208 modelViewMatrixIsUpToDate_ =
false;