00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "camera.h"
00026
00027
00028
00029
00030 #include "Eigen/LU"
00031 using namespace Eigen;
00032
00033 Camera::Camera()
00034 : mViewIsUptodate(false), mProjIsUptodate(false)
00035 {
00036 mViewMatrix.setIdentity();
00037
00038 mFovY = M_PI/3.;
00039 mNearDist = 0.1;
00040 mFarDist = 100.;
00041
00042 mVpX = 0;
00043 mVpY = 0;
00044
00045 setPosition(Vector3f::Constant(100.));
00046 setTarget(Vector3f::Zero());
00047 }
00048
00049 Camera& Camera::operator=(const Camera& other)
00050 {
00051 mViewIsUptodate = false;
00052 mProjIsUptodate = false;
00053
00054 mVpX = other.mVpX;
00055 mVpY = other.mVpY;
00056 mVpWidth = other.mVpWidth;
00057 mVpHeight = other.mVpHeight;
00058
00059 mTarget = other.mTarget;
00060 mFovY = other.mFovY;
00061 mNearDist = other.mNearDist;
00062 mFarDist = other.mFarDist;
00063
00064 mViewMatrix = other.mViewMatrix;
00065 mProjectionMatrix = other.mProjectionMatrix;
00066
00067 return *this;
00068 }
00069
00070 Camera::Camera(const Camera& other)
00071 {
00072 *this = other;
00073 }
00074
00075 Camera::~Camera()
00076 {
00077 }
00078
00079
00080 void Camera::setViewport(uint offsetx, uint offsety, uint width, uint height)
00081 {
00082 mVpX = offsetx;
00083 mVpY = offsety;
00084 mVpWidth = width;
00085 mVpHeight = height;
00086
00087 mProjIsUptodate = false;
00088 }
00089
00090 void Camera::setViewport(uint width, uint height)
00091 {
00092 mVpWidth = width;
00093 mVpHeight = height;
00094
00095 mProjIsUptodate = false;
00096 }
00097
00098 void Camera::setFovY(float value)
00099 {
00100 mFovY = value;
00101 mProjIsUptodate = false;
00102 }
00103
00104 Vector3f Camera::direction(void) const
00105 {
00106 return - (orientation() * Vector3f::UnitZ());
00107 }
00108 Vector3f Camera::up(void) const
00109 {
00110 return orientation() * Vector3f::UnitY();
00111 }
00112 Vector3f Camera::right(void) const
00113 {
00114 return orientation() * Vector3f::UnitX();
00115 }
00116
00117 void Camera::setDirection(const Vector3f& newDirection)
00118 {
00119
00120 Vector3f up = this->up();
00121
00122 Matrix3f camAxes;
00123
00124 camAxes.col(2) = (-newDirection).normalized();
00125 camAxes.col(0) = up.cross( camAxes.col(2) ).normalized();
00126 camAxes.col(1) = camAxes.col(2).cross( camAxes.col(0) ).normalized();
00127 setOrientation(Quaternionf(camAxes));
00128
00129 mViewIsUptodate = false;
00130 }
00131
00132 void Camera::setTarget(const Vector3f& target)
00133 {
00134 mTarget = target;
00135 if (!mTarget.isApprox(position()))
00136 {
00137 Vector3f newDirection = mTarget - position();
00138 setDirection(newDirection.normalized());
00139 }
00140 }
00141
00142 void Camera::setPosition(const Vector3f& p)
00143 {
00144 mFrame.position = p;
00145 mViewIsUptodate = false;
00146 }
00147
00148 void Camera::setOrientation(const Quaternionf& q)
00149 {
00150 mFrame.orientation = q;
00151 mViewIsUptodate = false;
00152 }
00153
00154 void Camera::setFrame(const Frame& f)
00155 {
00156 mFrame = f;
00157 mViewIsUptodate = false;
00158 }
00159
00160 void Camera::rotateAroundTarget(const Quaternionf& q)
00161 {
00162 Matrix4f mrot, mt, mtm;
00163
00164
00165 updateViewMatrix();
00166 Vector3f t = mViewMatrix * mTarget;
00167
00168 mViewMatrix = Translation3f(t)
00169 * q
00170 * Translation3f(-t)
00171 * mViewMatrix;
00172
00173 Quaternionf qa(mViewMatrix.linear());
00174 qa = qa.conjugate();
00175 setOrientation(qa);
00176 setPosition(- (qa * mViewMatrix.translation()) );
00177
00178 mViewIsUptodate = true;
00179 }
00180
00181 void Camera::localRotate(const Quaternionf& q)
00182 {
00183 float dist = (position() - mTarget).norm();
00184 setOrientation(orientation() * q);
00185 mTarget = position() + dist * direction();
00186 mViewIsUptodate = false;
00187 }
00188
00189 void Camera::zoom(float d)
00190 {
00191 float dist = (position() - mTarget).norm();
00192 if(dist > d)
00193 {
00194 setPosition(position() + direction() * d);
00195 mViewIsUptodate = false;
00196 }
00197 }
00198
00199 void Camera::localTranslate(const Vector3f& t)
00200 {
00201 Vector3f trans = orientation() * t;
00202 setPosition( position() + trans );
00203 setTarget( mTarget + trans );
00204
00205 mViewIsUptodate = false;
00206 }
00207
00208 void Camera::updateViewMatrix(void) const
00209 {
00210 if(!mViewIsUptodate)
00211 {
00212 Quaternionf q = orientation().conjugate();
00213 mViewMatrix.linear() = q.toRotationMatrix();
00214 mViewMatrix.translation() = - (mViewMatrix.linear() * position());
00215
00216 mViewIsUptodate = true;
00217 }
00218 }
00219
00220 const Affine3f& Camera::viewMatrix(void) const
00221 {
00222 updateViewMatrix();
00223 return mViewMatrix;
00224 }
00225
00226 void Camera::updateProjectionMatrix(void) const
00227 {
00228 if(!mProjIsUptodate)
00229 {
00230 mProjectionMatrix.setIdentity();
00231 float aspect = float(mVpWidth)/float(mVpHeight);
00232 float theta = mFovY*0.5;
00233 float range = mFarDist - mNearDist;
00234 float invtan = 1./tan(theta);
00235
00236 mProjectionMatrix(0,0) = invtan / aspect;
00237 mProjectionMatrix(1,1) = invtan;
00238 mProjectionMatrix(2,2) = -(mNearDist + mFarDist) / range;
00239 mProjectionMatrix(3,2) = -1;
00240 mProjectionMatrix(2,3) = -2 * mNearDist * mFarDist / range;
00241 mProjectionMatrix(3,3) = 0;
00242
00243 mProjIsUptodate = true;
00244 }
00245 }
00246
00247 const Matrix4f& Camera::projectionMatrix(void) const
00248 {
00249 updateProjectionMatrix();
00250 return mProjectionMatrix;
00251 }
00252 #if 0
00253 void Camera::activateGL(void)
00254 {
00255 glViewport(vpX(), vpY(), vpWidth(), vpHeight());
00256 gpu.loadMatrix(projectionMatrix(),GL_PROJECTION);
00257 gpu.loadMatrix(viewMatrix().matrix(),GL_MODELVIEW);
00258 }
00259 #endif
00260
00261
00262 Vector3f Camera::unProject(const Vector2f& uv, float depth) const
00263 {
00264 Matrix4f inv = mViewMatrix.inverse().matrix();
00265 return unProject(uv, depth, inv);
00266 }
00267
00268 Vector3f Camera::unProject(const Vector2f& uv, float depth, const Matrix4f& invModelview) const
00269 {
00270 updateViewMatrix();
00271 updateProjectionMatrix();
00272
00273 Vector3f a(2.*uv.x()/float(mVpWidth)-1., 2.*uv.y()/float(mVpHeight)-1., 1.);
00274 a.x() *= depth/mProjectionMatrix(0,0);
00275 a.y() *= depth/mProjectionMatrix(1,1);
00276 a.z() = -depth;
00277
00278 Vector4f b = invModelview * Vector4f(a.x(), a.y(), a.z(), 1.);
00279 return Vector3f(b.x(), b.y(), b.z());
00280 }