KGLLib
camera.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "camera.h"
00019
00020 #include <math.h>
00021
00022 #include <Eigen/LU>
00023
00024 using namespace Eigen;
00025
00026 namespace KGLLib
00027 {
00028
00029 Camera::Camera()
00030 {
00031 mFoV = 45.0f;
00032 mAspect = 1.0f;
00033 mDepthNear = 1.0f;
00034 mDepthFar = 100.0f;
00035 mPosition = Vector3f(-10, 0, 10);
00036 mLookAt = Vector3f(0, 0, 0);
00037 mUp = Vector3f(0, 1, 0);
00038 mModelviewMatrixDirty = true;
00039 mProjectionMatrixDirty = true;
00040 }
00041
00042 Camera::~Camera()
00043 {
00044 }
00045
00046 void Camera::setFoV(float fov)
00047 {
00048 mFoV = fov;
00049 mProjectionMatrixDirty = true;
00050 }
00051
00052 void Camera::setAspect(float aspect)
00053 {
00054 mAspect = aspect;
00055 mProjectionMatrixDirty = true;
00056 }
00057
00058 void Camera::setDepthRange(float near, float far)
00059 {
00060 mDepthNear = near;
00061 mDepthFar = far;
00062 mProjectionMatrixDirty = true;
00063 }
00064
00065 void Camera::setPosition(const Eigen::Vector3f& pos)
00066 {
00067 mPosition = pos;
00068 mModelviewMatrixDirty = true;
00069 }
00070
00071 void Camera::setLookAt(const Eigen::Vector3f& lookat)
00072 {
00073 mLookAt = lookat;
00074 mModelviewMatrixDirty = true;
00075 }
00076
00077 void Camera::setUp(const Eigen::Vector3f& up)
00078 {
00079 mUp = up;
00080 mModelviewMatrixDirty = true;
00081 }
00082
00083 void Camera::setDirection(const Eigen::Vector3f& dir)
00084 {
00085 setLookAt(mPosition + dir);
00086 }
00087
00088 void Camera::setViewport(int x, int y, int width, int height)
00089 {
00090 mViewport[0] = x;
00091 mViewport[1] = y;
00092 mViewport[2] = width;
00093 mViewport[3] = height;
00094 }
00095
00096 void Camera::applyPerspective()
00097 {
00098 if (mProjectionMatrixDirty) {
00099 recalculateProjectionMatrix();
00100 }
00101
00102 glMatrixMode(GL_PROJECTION);
00103 glLoadIdentity();
00104 glMultMatrixf(mProjectionMatrix.data());
00105 glMatrixMode(GL_MODELVIEW);
00106 }
00107
00108 void Camera::applyView(bool reset)
00109 {
00110 if (mModelviewMatrixDirty) {
00111 recalculateModelviewMatrix();
00112 }
00113
00114 if (reset) {
00115 glLoadIdentity();
00116 }
00117 glMultMatrixf(mModelviewMatrix.data());
00118 }
00119
00120 void Camera::applyViewport()
00121 {
00122 glViewport(mViewport[0], mViewport[1], mViewport[2], mViewport[3]);
00123 }
00124
00125 void Camera::recalculateModelviewMatrix()
00126 {
00127
00128 mModelviewMatrixDirty = false;
00129
00130 Vector3f forward = (mLookAt - mPosition).normalized();
00131
00132 Vector3f side = forward.cross(mUp).normalized();
00133
00134
00135 Vector3f up = side.cross(forward);
00136
00137 mModelviewMatrix.setIdentity();
00138 mModelviewMatrix.linear() << side.transpose(), up.transpose(), -forward.transpose();
00139 mModelviewMatrix.translate(-mPosition);
00140 }
00141
00142 void Camera::recalculateProjectionMatrix()
00143 {
00144
00145 mProjectionMatrixDirty = false;
00146 mProjectionMatrix.setIdentity();
00147 float radians = mFoV / 2 * M_PI / 180;
00148
00149 float deltaZ = mDepthFar - mDepthNear;
00150 float sine = ei_sin(radians);
00151 if ((deltaZ == 0) || (sine == 0) || (mAspect == 0)) {
00152 return;
00153 }
00154 float cotangent = ei_cos(radians) / sine;
00155
00156 mProjectionMatrix(0, 0) = cotangent / mAspect;
00157 mProjectionMatrix(1, 1) = cotangent;
00158 mProjectionMatrix(2, 2) = -(mDepthFar + mDepthNear) / deltaZ;
00159 mProjectionMatrix(3, 2) = -1;
00160 mProjectionMatrix(2, 3) = -2 * mDepthNear * mDepthFar / deltaZ;
00161 mProjectionMatrix(3, 3) = 0;
00162 }
00163
00164 void Camera::setModelviewMatrix(const Eigen::Transform3f& modelview)
00165 {
00166 mModelviewMatrix = modelview;
00167 mModelviewMatrixDirty = false;
00168 }
00169
00170 void Camera::setProjectionMatrix(const Eigen::Transform3f& projection)
00171 {
00172 mProjectionMatrix = projection;
00173 mProjectionMatrixDirty = false;
00174 }
00175
00176 Eigen::Transform3f Camera::modelviewMatrix() const
00177 {
00178 if (mModelviewMatrixDirty) {
00179 const_cast<Camera*>(this)->recalculateModelviewMatrix();
00180 }
00181 return mModelviewMatrix;
00182 }
00183
00184 Eigen::Transform3f Camera::projectionMatrix() const
00185 {
00186 if (mProjectionMatrixDirty) {
00187 const_cast<Camera*>(this)->recalculateProjectionMatrix();
00188 }
00189 return mProjectionMatrix;
00190 }
00191
00192 Eigen::Vector3f Camera::project(const Eigen::Vector3f& v, bool* ok) const
00193 {
00194
00195 Vector3f res;
00196 Vector4f p4 = projectionMatrix() * (modelviewMatrix() * Vector4f(v[0],v[1],v[2],1));
00197 if (p4.w()!=0)
00198 {
00199 res = p4.start<3>() / p4.w();
00200 res = (res * 0.5).cwise() + 0.5;
00201 res.start<2>() = Vector2f(mViewport[0],mViewport[1])
00202 + Vector2f(mViewport[2],mViewport[3]).cwise() * res.start<2>();
00203 if (ok)
00204 *ok = true;
00205 }
00206 else if (ok)
00207 *ok = false;
00208 return res;
00209 }
00210
00211 Eigen::Vector3f Camera::unProject(const Eigen::Vector3f& v, bool* ok) const
00212 {
00213
00214 if (ok) *ok = true;
00215 Vector4f a;
00216 a << (v.start<2>() - Vector2f(mViewport[0],mViewport[1]))
00217 .cwise() / Vector2f(mViewport[2],mViewport[3]),
00218 v.z(),
00219 1;
00220 a.start<3>() = a.start<3>() * 2 - Vector3f::Constant(1);
00221
00222
00223
00224 a = (projectionMatrix() * modelviewMatrix()).inverse() * a;
00225 if (a.w()==0)
00226 {
00227 if (ok) *ok = false;
00228 return a.start<3>();
00229 }
00230 return a.start<3>() / a.w();
00231 }
00232
00233
00234 }