/* QGLView Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru 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::Camera() { type_ = glCamera; fov_ = 60.; angle_limit_lower_xy = 0.f; angle_limit_upper_xy = 360.f; //setRotationX(90.f); depth_start = 0.1f; depth_end = 1000.f; mirror_x = mirror_y = false; } void Camera::anglesFromPoints() { //QVector3D dv = aim_ - pos_, tv; //tv = QVector3D(dv.x(), dv.y(), 0.); //angles_.setZ(atan2f(tv.x(), tv.y()) * rad2deg); //angles_.setY(piClamp(atan2f(tv.length(), dv.z()) * rad2deg, angle_limit_lower_xy, angle_limit_upper_xy) + 180.f); } QMatrix4x4 Camera::offsetMatrix() const { QMatrix4x4 ret; ret.translate(parent_ ? -offset_ : -aim()); return ret; } /* 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) { trans = c.trans; aim_dist = c.aim_dist; fov_ = c.fov_; angle_limit_lower_xy = c.angle_limit_lower_xy; angle_limit_upper_xy = c.angle_limit_upper_xy; mirror_x = c.mirror_x; mirror_y = c.mirror_y; depth_start = c.depth_start; depth_end = c.depth_end; buildTransform(); } ObjectBase * Camera::clone(bool withChildren) { Camera * o = new Camera(*this); //GLObjectBase::clone(withChildren); o->is_init = false; o->name_ = name_;// + "_copy"; o->scene_ = nullptr; o->children_.clear(); if (withChildren) { for (int i = 0; i < children_.size(); ++i) o->addChild(children_[i]->clone(withChildren)); } o->trans = trans; o->aim_dist = aim_dist; o->fov_ = fov_; o->angle_limit_lower_xy = angle_limit_lower_xy; o->angle_limit_upper_xy = angle_limit_upper_xy; o->mirror_x = mirror_x; o->mirror_y = mirror_y; o->depth_start = depth_start; o->depth_end = depth_end; o->meta = meta; return o; } QMatrix4x4 Camera::viewMatrix() const { QMatrix4x4 ret; //qDebug() << pos() << aim(); ret.translate(0., 0., -distance()); ret *= trans.matrixRotateScale().inverted(); //ret.rotate(angles_.y(), 1., 0., 0.); //ret.rotate(angles_.x(), 0., 1., 0.); //ret.rotate(angles_.z(), 0., 0., 1.); //pm.translate(-aim_); if (parent_) { QMatrix4x4 pmat = parent_->worldTransform(); offset_ = pmat.column(3).toVector3D(); pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.; pmat.translate(aim()); ret *= pmat.inverted(); } return ret; } QMatrix4x4 Camera::projectionMatrix(double aspect) const { return glMatrixPerspective(fov_, aspect, depth_start, depth_end); } void Camera::panZ(const float & a) { /*QVector3D dv = aim_ - pos_; float tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(angles_.z() + a); dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); aim_ = pos_ + dv; buildTransform();*/ } void Camera::panXY(const float & a) { /*QVector3D dv = aim_ - pos_; float tl = dv.length(), tc; angles_.setY(angles_.y() + a); angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); aim_ = pos_ + dv * tl; buildTransform();*/ } void Camera::rotateZ(const float & a) { /*QVector3D dv = aim_ - pos_; float tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(angles_.z() + a); dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); aim_ = pos_ + dv; buildTransform();*/ } void Camera::rotateXY(const float & a) { /*QVector3D dv = aim_ - pos_; float tl = dv.length(), tc; angles_.setY(angles_.y() + a); angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); aim_ = pos_ + dv * tl; buildTransform();*/ } void Camera::orbitZ(const float & a) { //qDebug() << rotation() << Transform::fromDirection(direction()); QVector3D pa = aim(); //trans.rotationRef() *= QQuaternion::fromEulerAngles(0, a, 0); ObjectBase::rotateZ(-a); move(pa - aim()); /*QVector3D dv = aim_ - pos_; float tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(angles_.z() + a); dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); pos_ = aim_ - dv; buildTransform();*/ } void Camera::orbitXY(const float & a) { QVector3D pa = aim(); //trans.rotationRef() *= QQuaternion::fromEulerAngles(a, 0, 0); ObjectBase::rotateX(-a); move(pa - aim()); //qDebug() << pos() << aim(); /*QVector3D dv = aim_ - pos_; float tl = dv.length(), tc; angles_.setY(angles_.y() + a); angles_.setY(piClamp(angles_.y(), angle_limit_lower_xy, angle_limit_upper_xy)); tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); pos_ = aim_ - dv * tl; buildTransform();*/ } void Camera::setAngleZ(const float & a) { /*QVector3D dv = aim_ - pos_; float tl = QVector2D(dv.x(), dv.y()).length(); angles_.setZ(a); dv = QVector3D(sinf(angles_.z() * deg2rad) * tl, cosf(angles_.z() * deg2rad) * tl, dv.z()); aim_ = pos_ + dv; buildTransform();*/ } void Camera::setAngleXY(const float & a) { /*QVector3D dv = aim_ - pos_; float tl = dv.length(), tc; angles_.setY(a); tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); //pos_ = aim_ - dv; aim_ = pos_ + dv * tl; buildTransform();*/ //anglesFromPoints(); } void Camera::moveForward(const float & x, bool withZ) { /*Vector3D dv;// = aim_ - pos_; float tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, 0.); if (withZ) dv.setZ(-cosf(angles_.y() * deg2rad)); dv.normalize(); dv *= x; pos_ += dv; aim_ += dv; buildTransform();*/ } void Camera::moveLeft(const float & x, bool withZ) { /*QVector3D dv;// = aim_ - pos_; float tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad - float(M_PI_2)) * tc, cosf(angles_.z() * deg2rad - float(M_PI_2)) * tc, 0.f); if (withZ) dv.setZ(-sinf(angles_.x() * deg2rad)); dv.normalize(); dv *= x; pos_ += dv; aim_ += dv; buildTransform();*/ } void Camera::moveUp(const float & x, bool onlyZ) { /*QVector3D dv; if (onlyZ) dv = QVector3D(0., 0., x); else { float tc = cosf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -sinf(angles_.y() * deg2rad)); dv.normalize(); dv *= x; } pos_ += dv; aim_ += dv; buildTransform();*/ } /* void Camera::flyCloser(const float & s) { QVector3D dv = aim_ - pos_; float tl = dv.length() / (1.f + s), tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); pos_ = aim_ - dv * tl; buildTransform(); } void Camera::flyFarer(const float & s) { QVector3D dv = aim_ - pos_; float tl = dv.length() * (1.f + s), tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); pos_ = aim_ - dv * tl; buildTransform(); } void Camera::flyToDistance(const float & d) { QVector3D dv = aim_ - pos_; float tc = -sinf(angles_.y() * deg2rad); dv = QVector3D(sinf(angles_.z() * deg2rad) * tc, cosf(angles_.z() * deg2rad) * tc, -cosf(angles_.y() * deg2rad)); pos_ = aim_ - dv * d; buildTransform(); } */