1 // Copyright (C) 2012-2019 The VPaint Developers. 2 // See the COPYRIGHT file at the top-level directory of this distribution 3 // and at https://github.com/dalboris/vpaint/blob/master/COPYRIGHT 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #ifndef GLWIDGET_CAMERA_H 18 #define GLWIDGET_CAMERA_H 19 20 #include <Eigen/Core> 21 #include <Eigen/Geometry> 22 23 /* 24 * The Camera is defined by: 25 * - The position of its focus point 26 * - Its distance and angle around this point 27 * - Its aperture 28 * 29 * There are only 2 angles to define the orientation of the camera: yaw and 30 * pitch (no roll). This is a voluntary loss of degree of freedom: we force 31 * the horizon line to be horizontal on screen (avoid getting lost and/or 32 * sea-sick). 33 * 34 */ 35 36 class GLWidget_Camera 37 { 38 public: 39 // initialization: correctly positionned to see a unit cube GLWidget_Camera()40 GLWidget_Camera() : 41 r_(4), theta_(3.14/10), phi_(3.14/6), 42 focus_x_(0), focus_y_(0), focus_z_(0), 43 fovy_(3.14/4) 44 { 45 setDirty_(); 46 } 47 48 // Camera position and orientation (= View Matrix) r()49 double r() const { return r_; } theta()50 double theta() const { return theta_; } phi()51 double phi() const { return phi_; } focus_x()52 double focus_x() const { return focus_x_; } focus_y()53 double focus_y() const { return focus_y_; } focus_z()54 double focus_z() const { return focus_z_; } 55 56 // Camera field of view (= Projection Matrix) fovy()57 double fovy() const { return fovy_; } 58 59 // Setters setR(double r)60 void setR(double r) { r_=r; setDirty_(); } setTheta(double theta)61 void setTheta(double theta) { theta_=theta; setDirty_(); } setPhi(double phi)62 void setPhi(double phi) { phi_=phi; setDirty_(); } setFocus_x(double focus_x)63 void setFocus_x(double focus_x) { focus_x_=focus_x; setDirty_(); } setFocus_y(double focus_y)64 void setFocus_y(double focus_y) { focus_y_=focus_y; setDirty_(); } setFocus_z(double focus_z)65 void setFocus_z(double focus_z) { focus_z_=focus_z; setDirty_(); } setFovy(double fovy)66 void setFovy(double fovy) { fovy_=fovy; setDirty_(); } 67 68 // Get matrices viewMatrix()69 Eigen::Affine3d viewMatrix() const 70 { 71 computeViewMatrix_(); 72 return viewMatrix_; 73 } 74 viewMatrixInverse()75 Eigen::Affine3d viewMatrixInverse() const 76 { 77 computeViewMatrixInverse_(); 78 return viewMatrixInverse_; 79 } 80 81 // convenient methods to access other geometric properties position()82 Eigen::Vector3d position() const 83 { 84 double cos_theta = std::cos(theta()); 85 double sin_theta = std::sin(theta()); 86 double cos_phi = std::cos(phi()); 87 double sin_phi = std::sin(phi()); 88 89 return Eigen::Vector3d( 90 focus_x() + r() * cos_theta * sin_phi, 91 focus_y() + r() * sin_theta, 92 focus_z() + r() * cos_theta * cos_phi); 93 } 94 focusPoint()95 Eigen::Vector3d focusPoint() const 96 { 97 return Eigen::Vector3d(focus_x(), focus_y(), focus_z()); 98 } 99 upDirection()100 Eigen::Vector3d upDirection() const 101 { 102 double cos_theta = std::cos(theta()); 103 double sin_theta = std::sin(theta()); 104 double cos_phi = std::cos(phi()); 105 double sin_phi = std::sin(phi()); 106 107 return Eigen::Vector3d( 108 - sin_theta * sin_phi, 109 cos_theta, 110 - sin_theta * cos_phi); 111 } 112 113 114 private: 115 // Camera parameters 116 double r_; 117 double theta_; 118 double phi_; 119 double focus_x_; 120 double focus_y_; 121 double focus_z_; 122 double fovy_; 123 124 // Matrix 125 mutable bool viewMatrixDirty_; 126 mutable bool viewMatrixInverseDirty_; 127 mutable Eigen::Affine3d viewMatrix_; 128 mutable Eigen::Affine3d viewMatrixInverse_; setDirty_()129 void setDirty_() 130 { 131 viewMatrixDirty_ = true; 132 viewMatrixInverseDirty_ = true; 133 } computeViewMatrix_()134 void computeViewMatrix_() const 135 { 136 if(viewMatrixDirty_) 137 { 138 // [...] compute it 139 viewMatrixDirty_ = false; 140 } 141 } computeViewMatrixInverse_()142 void computeViewMatrixInverse_() const 143 { 144 if(viewMatrixInverseDirty_) 145 { 146 computeViewMatrix_(); 147 viewMatrixInverse_ = viewMatrix_.inverse(); 148 viewMatrixInverseDirty_ = false; 149 } 150 } 151 152 public: 153 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 154 155 }; 156 157 158 #endif 159