1*bf2c3715SXin Li // This file is part of Eigen, a lightweight C++ template library
2*bf2c3715SXin Li // for linear algebra.
3*bf2c3715SXin Li //
4*bf2c3715SXin Li // Copyright (C) 2008 Gael Guennebaud <[email protected]>
5*bf2c3715SXin Li //
6*bf2c3715SXin Li // This Source Code Form is subject to the terms of the Mozilla
7*bf2c3715SXin Li // Public License v. 2.0. If a copy of the MPL was not distributed
8*bf2c3715SXin Li // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9*bf2c3715SXin Li
10*bf2c3715SXin Li #include "camera.h"
11*bf2c3715SXin Li
12*bf2c3715SXin Li #include "gpuhelper.h"
13*bf2c3715SXin Li #include <GL/glu.h>
14*bf2c3715SXin Li
15*bf2c3715SXin Li #include "Eigen/LU"
16*bf2c3715SXin Li using namespace Eigen;
17*bf2c3715SXin Li
Camera()18*bf2c3715SXin Li Camera::Camera()
19*bf2c3715SXin Li : mViewIsUptodate(false), mProjIsUptodate(false)
20*bf2c3715SXin Li {
21*bf2c3715SXin Li mViewMatrix.setIdentity();
22*bf2c3715SXin Li
23*bf2c3715SXin Li mFovY = M_PI/3.;
24*bf2c3715SXin Li mNearDist = 1.;
25*bf2c3715SXin Li mFarDist = 50000.;
26*bf2c3715SXin Li
27*bf2c3715SXin Li mVpX = 0;
28*bf2c3715SXin Li mVpY = 0;
29*bf2c3715SXin Li
30*bf2c3715SXin Li setPosition(Vector3f::Constant(100.));
31*bf2c3715SXin Li setTarget(Vector3f::Zero());
32*bf2c3715SXin Li }
33*bf2c3715SXin Li
operator =(const Camera & other)34*bf2c3715SXin Li Camera& Camera::operator=(const Camera& other)
35*bf2c3715SXin Li {
36*bf2c3715SXin Li mViewIsUptodate = false;
37*bf2c3715SXin Li mProjIsUptodate = false;
38*bf2c3715SXin Li
39*bf2c3715SXin Li mVpX = other.mVpX;
40*bf2c3715SXin Li mVpY = other.mVpY;
41*bf2c3715SXin Li mVpWidth = other.mVpWidth;
42*bf2c3715SXin Li mVpHeight = other.mVpHeight;
43*bf2c3715SXin Li
44*bf2c3715SXin Li mTarget = other.mTarget;
45*bf2c3715SXin Li mFovY = other.mFovY;
46*bf2c3715SXin Li mNearDist = other.mNearDist;
47*bf2c3715SXin Li mFarDist = other.mFarDist;
48*bf2c3715SXin Li
49*bf2c3715SXin Li mViewMatrix = other.mViewMatrix;
50*bf2c3715SXin Li mProjectionMatrix = other.mProjectionMatrix;
51*bf2c3715SXin Li
52*bf2c3715SXin Li return *this;
53*bf2c3715SXin Li }
54*bf2c3715SXin Li
Camera(const Camera & other)55*bf2c3715SXin Li Camera::Camera(const Camera& other)
56*bf2c3715SXin Li {
57*bf2c3715SXin Li *this = other;
58*bf2c3715SXin Li }
59*bf2c3715SXin Li
~Camera()60*bf2c3715SXin Li Camera::~Camera()
61*bf2c3715SXin Li {
62*bf2c3715SXin Li }
63*bf2c3715SXin Li
64*bf2c3715SXin Li
setViewport(uint offsetx,uint offsety,uint width,uint height)65*bf2c3715SXin Li void Camera::setViewport(uint offsetx, uint offsety, uint width, uint height)
66*bf2c3715SXin Li {
67*bf2c3715SXin Li mVpX = offsetx;
68*bf2c3715SXin Li mVpY = offsety;
69*bf2c3715SXin Li mVpWidth = width;
70*bf2c3715SXin Li mVpHeight = height;
71*bf2c3715SXin Li
72*bf2c3715SXin Li mProjIsUptodate = false;
73*bf2c3715SXin Li }
74*bf2c3715SXin Li
setViewport(uint width,uint height)75*bf2c3715SXin Li void Camera::setViewport(uint width, uint height)
76*bf2c3715SXin Li {
77*bf2c3715SXin Li mVpWidth = width;
78*bf2c3715SXin Li mVpHeight = height;
79*bf2c3715SXin Li
80*bf2c3715SXin Li mProjIsUptodate = false;
81*bf2c3715SXin Li }
82*bf2c3715SXin Li
setFovY(float value)83*bf2c3715SXin Li void Camera::setFovY(float value)
84*bf2c3715SXin Li {
85*bf2c3715SXin Li mFovY = value;
86*bf2c3715SXin Li mProjIsUptodate = false;
87*bf2c3715SXin Li }
88*bf2c3715SXin Li
direction(void) const89*bf2c3715SXin Li Vector3f Camera::direction(void) const
90*bf2c3715SXin Li {
91*bf2c3715SXin Li return - (orientation() * Vector3f::UnitZ());
92*bf2c3715SXin Li }
up(void) const93*bf2c3715SXin Li Vector3f Camera::up(void) const
94*bf2c3715SXin Li {
95*bf2c3715SXin Li return orientation() * Vector3f::UnitY();
96*bf2c3715SXin Li }
right(void) const97*bf2c3715SXin Li Vector3f Camera::right(void) const
98*bf2c3715SXin Li {
99*bf2c3715SXin Li return orientation() * Vector3f::UnitX();
100*bf2c3715SXin Li }
101*bf2c3715SXin Li
setDirection(const Vector3f & newDirection)102*bf2c3715SXin Li void Camera::setDirection(const Vector3f& newDirection)
103*bf2c3715SXin Li {
104*bf2c3715SXin Li // TODO implement it computing the rotation between newDirection and current dir ?
105*bf2c3715SXin Li Vector3f up = this->up();
106*bf2c3715SXin Li
107*bf2c3715SXin Li Matrix3f camAxes;
108*bf2c3715SXin Li
109*bf2c3715SXin Li camAxes.col(2) = (-newDirection).normalized();
110*bf2c3715SXin Li camAxes.col(0) = up.cross( camAxes.col(2) ).normalized();
111*bf2c3715SXin Li camAxes.col(1) = camAxes.col(2).cross( camAxes.col(0) ).normalized();
112*bf2c3715SXin Li setOrientation(Quaternionf(camAxes));
113*bf2c3715SXin Li
114*bf2c3715SXin Li mViewIsUptodate = false;
115*bf2c3715SXin Li }
116*bf2c3715SXin Li
setTarget(const Vector3f & target)117*bf2c3715SXin Li void Camera::setTarget(const Vector3f& target)
118*bf2c3715SXin Li {
119*bf2c3715SXin Li mTarget = target;
120*bf2c3715SXin Li if (!mTarget.isApprox(position()))
121*bf2c3715SXin Li {
122*bf2c3715SXin Li Vector3f newDirection = mTarget - position();
123*bf2c3715SXin Li setDirection(newDirection.normalized());
124*bf2c3715SXin Li }
125*bf2c3715SXin Li }
126*bf2c3715SXin Li
setPosition(const Vector3f & p)127*bf2c3715SXin Li void Camera::setPosition(const Vector3f& p)
128*bf2c3715SXin Li {
129*bf2c3715SXin Li mFrame.position = p;
130*bf2c3715SXin Li mViewIsUptodate = false;
131*bf2c3715SXin Li }
132*bf2c3715SXin Li
setOrientation(const Quaternionf & q)133*bf2c3715SXin Li void Camera::setOrientation(const Quaternionf& q)
134*bf2c3715SXin Li {
135*bf2c3715SXin Li mFrame.orientation = q;
136*bf2c3715SXin Li mViewIsUptodate = false;
137*bf2c3715SXin Li }
138*bf2c3715SXin Li
setFrame(const Frame & f)139*bf2c3715SXin Li void Camera::setFrame(const Frame& f)
140*bf2c3715SXin Li {
141*bf2c3715SXin Li mFrame = f;
142*bf2c3715SXin Li mViewIsUptodate = false;
143*bf2c3715SXin Li }
144*bf2c3715SXin Li
rotateAroundTarget(const Quaternionf & q)145*bf2c3715SXin Li void Camera::rotateAroundTarget(const Quaternionf& q)
146*bf2c3715SXin Li {
147*bf2c3715SXin Li Matrix4f mrot, mt, mtm;
148*bf2c3715SXin Li
149*bf2c3715SXin Li // update the transform matrix
150*bf2c3715SXin Li updateViewMatrix();
151*bf2c3715SXin Li Vector3f t = mViewMatrix * mTarget;
152*bf2c3715SXin Li
153*bf2c3715SXin Li mViewMatrix = Translation3f(t)
154*bf2c3715SXin Li * q
155*bf2c3715SXin Li * Translation3f(-t)
156*bf2c3715SXin Li * mViewMatrix;
157*bf2c3715SXin Li
158*bf2c3715SXin Li Quaternionf qa(mViewMatrix.linear());
159*bf2c3715SXin Li qa = qa.conjugate();
160*bf2c3715SXin Li setOrientation(qa);
161*bf2c3715SXin Li setPosition(- (qa * mViewMatrix.translation()) );
162*bf2c3715SXin Li
163*bf2c3715SXin Li mViewIsUptodate = true;
164*bf2c3715SXin Li }
165*bf2c3715SXin Li
localRotate(const Quaternionf & q)166*bf2c3715SXin Li void Camera::localRotate(const Quaternionf& q)
167*bf2c3715SXin Li {
168*bf2c3715SXin Li float dist = (position() - mTarget).norm();
169*bf2c3715SXin Li setOrientation(orientation() * q);
170*bf2c3715SXin Li mTarget = position() + dist * direction();
171*bf2c3715SXin Li mViewIsUptodate = false;
172*bf2c3715SXin Li }
173*bf2c3715SXin Li
zoom(float d)174*bf2c3715SXin Li void Camera::zoom(float d)
175*bf2c3715SXin Li {
176*bf2c3715SXin Li float dist = (position() - mTarget).norm();
177*bf2c3715SXin Li if(dist > d)
178*bf2c3715SXin Li {
179*bf2c3715SXin Li setPosition(position() + direction() * d);
180*bf2c3715SXin Li mViewIsUptodate = false;
181*bf2c3715SXin Li }
182*bf2c3715SXin Li }
183*bf2c3715SXin Li
localTranslate(const Vector3f & t)184*bf2c3715SXin Li void Camera::localTranslate(const Vector3f& t)
185*bf2c3715SXin Li {
186*bf2c3715SXin Li Vector3f trans = orientation() * t;
187*bf2c3715SXin Li setPosition( position() + trans );
188*bf2c3715SXin Li setTarget( mTarget + trans );
189*bf2c3715SXin Li
190*bf2c3715SXin Li mViewIsUptodate = false;
191*bf2c3715SXin Li }
192*bf2c3715SXin Li
updateViewMatrix(void) const193*bf2c3715SXin Li void Camera::updateViewMatrix(void) const
194*bf2c3715SXin Li {
195*bf2c3715SXin Li if(!mViewIsUptodate)
196*bf2c3715SXin Li {
197*bf2c3715SXin Li Quaternionf q = orientation().conjugate();
198*bf2c3715SXin Li mViewMatrix.linear() = q.toRotationMatrix();
199*bf2c3715SXin Li mViewMatrix.translation() = - (mViewMatrix.linear() * position());
200*bf2c3715SXin Li
201*bf2c3715SXin Li mViewIsUptodate = true;
202*bf2c3715SXin Li }
203*bf2c3715SXin Li }
204*bf2c3715SXin Li
viewMatrix(void) const205*bf2c3715SXin Li const Affine3f& Camera::viewMatrix(void) const
206*bf2c3715SXin Li {
207*bf2c3715SXin Li updateViewMatrix();
208*bf2c3715SXin Li return mViewMatrix;
209*bf2c3715SXin Li }
210*bf2c3715SXin Li
updateProjectionMatrix(void) const211*bf2c3715SXin Li void Camera::updateProjectionMatrix(void) const
212*bf2c3715SXin Li {
213*bf2c3715SXin Li if(!mProjIsUptodate)
214*bf2c3715SXin Li {
215*bf2c3715SXin Li mProjectionMatrix.setIdentity();
216*bf2c3715SXin Li float aspect = float(mVpWidth)/float(mVpHeight);
217*bf2c3715SXin Li float theta = mFovY*0.5;
218*bf2c3715SXin Li float range = mFarDist - mNearDist;
219*bf2c3715SXin Li float invtan = 1./tan(theta);
220*bf2c3715SXin Li
221*bf2c3715SXin Li mProjectionMatrix(0,0) = invtan / aspect;
222*bf2c3715SXin Li mProjectionMatrix(1,1) = invtan;
223*bf2c3715SXin Li mProjectionMatrix(2,2) = -(mNearDist + mFarDist) / range;
224*bf2c3715SXin Li mProjectionMatrix(3,2) = -1;
225*bf2c3715SXin Li mProjectionMatrix(2,3) = -2 * mNearDist * mFarDist / range;
226*bf2c3715SXin Li mProjectionMatrix(3,3) = 0;
227*bf2c3715SXin Li
228*bf2c3715SXin Li mProjIsUptodate = true;
229*bf2c3715SXin Li }
230*bf2c3715SXin Li }
231*bf2c3715SXin Li
projectionMatrix(void) const232*bf2c3715SXin Li const Matrix4f& Camera::projectionMatrix(void) const
233*bf2c3715SXin Li {
234*bf2c3715SXin Li updateProjectionMatrix();
235*bf2c3715SXin Li return mProjectionMatrix;
236*bf2c3715SXin Li }
237*bf2c3715SXin Li
activateGL(void)238*bf2c3715SXin Li void Camera::activateGL(void)
239*bf2c3715SXin Li {
240*bf2c3715SXin Li glViewport(vpX(), vpY(), vpWidth(), vpHeight());
241*bf2c3715SXin Li gpu.loadMatrix(projectionMatrix(),GL_PROJECTION);
242*bf2c3715SXin Li gpu.loadMatrix(viewMatrix().matrix(),GL_MODELVIEW);
243*bf2c3715SXin Li }
244*bf2c3715SXin Li
245*bf2c3715SXin Li
unProject(const Vector2f & uv,float depth) const246*bf2c3715SXin Li Vector3f Camera::unProject(const Vector2f& uv, float depth) const
247*bf2c3715SXin Li {
248*bf2c3715SXin Li Matrix4f inv = mViewMatrix.inverse().matrix();
249*bf2c3715SXin Li return unProject(uv, depth, inv);
250*bf2c3715SXin Li }
251*bf2c3715SXin Li
unProject(const Vector2f & uv,float depth,const Matrix4f & invModelview) const252*bf2c3715SXin Li Vector3f Camera::unProject(const Vector2f& uv, float depth, const Matrix4f& invModelview) const
253*bf2c3715SXin Li {
254*bf2c3715SXin Li updateViewMatrix();
255*bf2c3715SXin Li updateProjectionMatrix();
256*bf2c3715SXin Li
257*bf2c3715SXin Li Vector3f a(2.*uv.x()/float(mVpWidth)-1., 2.*uv.y()/float(mVpHeight)-1., 1.);
258*bf2c3715SXin Li a.x() *= depth/mProjectionMatrix(0,0);
259*bf2c3715SXin Li a.y() *= depth/mProjectionMatrix(1,1);
260*bf2c3715SXin Li a.z() = -depth;
261*bf2c3715SXin Li // FIXME /\/|
262*bf2c3715SXin Li Vector4f b = invModelview * Vector4f(a.x(), a.y(), a.z(), 1.);
263*bf2c3715SXin Li return Vector3f(b.x(), b.y(), b.z());
264*bf2c3715SXin Li }
265