/* QGLView Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "gltypes.h" #include "qglview.h" Camera * currentCamera; QMatrix4x4 globCameraMatrix; Camera::Camera() { fov_ = 60.; angle_limit_lower_xy = 0.; angle_limit_upper_xy = 360.; angles_.setY(270.); depth_start = 0.1; depth_end = 1000.; mirror_x = mirror_y = false; } void Camera::anglesFromPoints() { QVector3D dv = aim_ - pos_, tv; tv = QVector3D(dv.x(), dv.y(), 0.); angles_.setZ(atan2(tv.x(), tv.y()) * rad2deg); angles_.setY(piClamp(atan2(tv.length(), dv.z()) * rad2deg, angle_limit_lower_xy, angle_limit_upper_xy) + 180.); } void Camera::apply(const GLdouble & aspect) { glMatrixMode(GL_PROJECTION); if (aspect <= 1.) glScaled(aspect, aspect, 1.); QMatrix4x4 pm;// = glMatrixPerspective(fov_, aspect, depth_start, depth_end); pm.perspective(fov_, aspect, depth_start, depth_end); //qDebug() << pm << glMatrixPerspective(fov_, aspect, depth_start, depth_end);; setGLMatrix(pm); glMatrixMode(GL_MODELVIEW); pm.setToIdentity(); //qDebug() << pm; pm.translate(0., 0., -distance()); pm.rotate(angles_.y(), 1., 0., 0.); pm.rotate(angles_.x(), 0., 1., 0.); pm.rotate(angles_.z(), 0., 0., 1.); //pm.translate(-aim_); if (parent_) { pm.translate(-aim_); pm *= parent_->worldTransform().inverted(); } setGLMatrix(pm); //qDebug() << angles_; } /* void Camera::localTransform(QMatrix4x4 & m) { return; if (parent_) m *= parent_->worldTransform(); QMatrix4x4 ret; //qDebug() << "local camera"; ret.translate(0., 0., -distance()); ret.rotate(angles_.y(), 1., 0., 0.); ret.rotate(angles_.x(), 0., 1., 0.); ret.rotate(angles_.z(), 0., 0., 1.); //m *= ret.inverted(); } */ void Camera::assign(const Camera & c) { pos_ = c.pos_; aim_ = c.aim_; fov_ = c.fov_; angles_ = c.angles_; angle_limit_lower_xy = c.angle_limit_lower_xy; angle_limit_upper_xy = c.angle_limit_upper_xy; buildTransform(); } void Camera::panZ(const double & a) { QVector3D dv = aim_ - pos_; double tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(angles_.z() + a); dv = QVector3D(sin(angles_.z() * deg2rad) * tl, cos(angles_.z() * deg2rad) * tl, dv.z()); aim_ = pos_ + dv; buildTransform(); } void Camera::panXY(const double & a) { QVector3D dv = aim_ - pos_; double tl = dv.length(), tc; angles_.setY(angles_.y() + a); angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); tc = -sin(angles_.y() * deg2rad); dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); aim_ = pos_ + dv * tl; buildTransform(); } void Camera::rotateZ(const double & a) { QVector3D dv = aim_ - pos_; double tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(angles_.z() + a); dv = QVector3D(sin(angles_.z() * deg2rad) * tl, cos(angles_.z() * deg2rad) * tl, dv.z()); aim_ = pos_ + dv; buildTransform(); } void Camera::rotateXY(const double & a) { QVector3D dv = aim_ - pos_; double tl = dv.length(), tc; angles_.setY(angles_.y() + a); angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); tc = -sin(angles_.y() * deg2rad); dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); aim_ = pos_ + dv * tl; buildTransform(); } void Camera::orbitZ(const double & a) { QVector3D dv = aim_ - pos_; double tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(angles_.z() + a); dv = QVector3D(sin(angles_.z() * deg2rad) * tl, cos(angles_.z() * deg2rad) * tl, dv.z()); pos_ = aim_ - dv; buildTransform(); } void Camera::orbitXY(const double & a) { QVector3D dv = aim_ - pos_; double tl = dv.length(), tc; angles_.setY(angles_.y() + a); angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); tc = -sin(angles_.y() * deg2rad); dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); pos_ = aim_ - dv * tl; buildTransform(); } void Camera::setAngleZ(const double & a) { QVector3D dv = aim_ - pos_; double tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(a); dv = QVector3D(sin(angles_.z() * deg2rad) * tl, cos(angles_.z() * deg2rad) * tl, dv.z()); aim_ = pos_ + dv; buildTransform(); } void Camera::setAngleXY(const double & a) { QVector3D dv = aim_ - pos_; double tl = dv.length(), tc; angles_.setY(a); tc = -sin(angles_.y() * deg2rad); dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); //pos_ = aim_ - dv; aim_ = pos_ + dv * tl; buildTransform(); //anglesFromPoints(); } void Camera::moveForward(const double & x, bool withZ) { QVector3D dv;// = aim_ - pos_; double tc = -sin(angles_.y() * deg2rad); dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, 0.); if (withZ) dv.setZ(-cos(angles_.y() * deg2rad)); dv.normalize(); dv *= x; pos_ += dv; aim_ += dv; buildTransform(); } void Camera::moveLeft(const double & x, bool withZ) { QVector3D dv;// = aim_ - pos_; double tc = -sin(angles_.y() * deg2rad); dv = QVector3D(sin(angles_.z() * deg2rad - M_PI_2) * tc, cos(angles_.z() * deg2rad - M_PI_2) * tc, 0.); if (withZ) dv.setZ(-sin(angles_.x() * deg2rad)); dv.normalize(); dv *= x; pos_ += dv; aim_ += dv; buildTransform(); } void Camera::moveUp(const double & x, bool onlyZ) { QVector3D dv; if (onlyZ) dv = QVector3D(0., 0., x); else { double tc = cos(angles_.y() * deg2rad); dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -sin(angles_.y() * deg2rad)); dv.normalize(); dv *= x; } pos_ += dv; aim_ += dv; buildTransform(); } void Camera::flyCloser(const double & s) { QVector3D dv = aim_ - pos_; double tl = dv.length() / (1. + s), tc = -sin(angles_.y() * deg2rad); dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); pos_ = aim_ - dv * tl; buildTransform(); } void Camera::flyFarer(const double & s) { QVector3D dv = aim_ - pos_; double tl = dv.length() * (1. + s), tc = -sin(angles_.y() * deg2rad); dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); pos_ = aim_ - dv * tl; buildTransform(); } void Camera::flyToDistance(const double & d) { QVector3D dv = aim_ - pos_; double tc = -sin(angles_.y() * deg2rad); dv = QVector3D(sin(angles_.z() * deg2rad) * tc, cos(angles_.z() * deg2rad) * tc, -cos(angles_.y() * deg2rad)); pos_ = aim_ - dv * d; buildTransform(); } /* QVector3D Camera::pointFromViewport(int x_, int y_, double z_) { GLsizei mx = x_, my = viewport[3] - y_, mz = z_; GLdouble x,y,z; gluUnProject(mx, my, mz, modelview, projection, viewport, &x, &y, &z); return QVector3D(x,y,z); } */