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