[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    playground/libs/kgllib/extras/kgllib
From:       Rivo Laks <rivolaks () hot ! ee>
Date:       2008-03-04 17:58:25
Message-ID: 1204653505.447433.26387.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 782264 by rivol:

Camera now calculates and stores modelview and projection matrices
  instead of using utility functions like gluLookAt().
  The advantage is that you can now get/set those matrices directly
  if necessary (instead of using e.g. setPosition()).

 M  +97 -4     camera.cpp  
 M  +16 -0     camera.h  


--- trunk/playground/libs/kgllib/extras/kgllib/camera.cpp #782263:782264
@@ -19,6 +19,9 @@
 
 #include <kgllib.h>
 
+#include <math.h>
+
+
 using namespace Eigen;
 
 namespace KGLLib
@@ -33,6 +36,8 @@
     mPosition = Vector3f(-10, 0, 10);
     mLookAt = Vector3f(0, 0, 0);
     mUp = Vector3f(0, 1, 0);
+    mModelviewMatrixDirty = true;
+    mProjectionMatrixDirty = true;
 }
 
 Camera::~Camera()
@@ -42,32 +47,38 @@
 void Camera::setFoV(float fov)
 {
     mFoV = fov;
+    mProjectionMatrixDirty = true;
 }
 
 void Camera::setAspect(float aspect)
 {
     mAspect = aspect;
+    mProjectionMatrixDirty = true;
 }
 
 void Camera::setDepthRange(float near, float far)
 {
     mDepthNear = near;
     mDepthFar = far;
+    mProjectionMatrixDirty = true;
 }
 
 void Camera::setPosition(const Eigen::Vector3f& pos)
 {
     mPosition = pos;
+    mModelviewMatrixDirty = true;
 }
 
 void Camera::setLookAt(const Eigen::Vector3f& lookat)
 {
     mLookAt = lookat;
+    mModelviewMatrixDirty = true;
 }
 
 void Camera::setUp(const Eigen::Vector3f& up)
 {
     mUp = up;
+    mModelviewMatrixDirty = true;
 }
 
 void Camera::setDirection(const Eigen::Vector3f& dir)
@@ -77,20 +88,102 @@
 
 void Camera::applyPerspective()
 {
+    if (mProjectionMatrixDirty) {
+        recalculateProjectionMatrix();
+    }
+
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    gluPerspective(mFoV, mAspect, mDepthNear, mDepthFar);
+    glMultMatrixf(mProjectionMatrix.array());
     glMatrixMode(GL_MODELVIEW);
 }
 
 void Camera::applyView(bool reset)
 {
+    if (mModelviewMatrixDirty) {
+        recalculateModelviewMatrix();
+    }
+
     if (reset) {
         glLoadIdentity();
     }
-    gluLookAt(mPosition.x(), mPosition.y(), mPosition.z(),
-              mLookAt.x(), mLookAt.y(), mLookAt.z(),
-              mUp.x(), mUp.y(), mUp.z());
+    glMultMatrixf(mModelviewMatrix.array());
 }
 
+void Camera::recalculateModelviewMatrix()
+{
+    // Code from Mesa project, src/glu/sgi/libutil/project.c
+    mModelviewMatrixDirty = false;
+    // Our looking direction
+    Vector3f forward = mLookAt - mPosition;
+    forward.normalize();
+
+    Vector3f side = forward.cross(mUp);
+    side.normalize();
+
+    // Recompute up vector, using cross product
+    Vector3f up = side.cross(forward);
+
+    // Linear component of the modelview matrix
+    Matrix3f linear;
+    linear.setRow(0, side);
+    linear.setRow(1, up);
+    linear.setRow(2, -forward);
+
+    mModelviewMatrix.loadIdentity();
+    mModelviewMatrix.setLinearComponent(linear);
+    mModelviewMatrix.translate(-mPosition);
 }
+
+void Camera::recalculateProjectionMatrix()
+{
+    // Code from Mesa project, src/glu/sgi/libutil/project.c
+    mProjectionMatrixDirty = false;
+    mProjectionMatrix.loadIdentity();
+    float radians = mFoV / 2 * M_PI / 180;
+
+    float deltaZ = mDepthFar - mDepthNear;
+    float sine = sin(radians);
+    if ((deltaZ == 0) || (sine == 0) || (mAspect == 0)) {
+        return;
+    }
+    float cotangent = cos(radians) / sine;
+
+    mProjectionMatrix(0, 0) = cotangent / mAspect;
+    mProjectionMatrix(1, 1) = cotangent;
+    mProjectionMatrix(2, 2) = -(mDepthFar + mDepthNear) / deltaZ;
+    mProjectionMatrix(3, 2) = -1;
+    mProjectionMatrix(2, 3) = -2 * mDepthNear * mDepthFar / deltaZ;
+    mProjectionMatrix(3, 3) = 0;
+}
+
+void Camera::setModelviewMatrix(const Eigen::MatrixP3f& modelview)
+{
+    mModelviewMatrix = modelview;
+    mModelviewMatrixDirty = false;
+}
+
+void Camera::setProjectionMatrix(const Eigen::MatrixP3f& projection)
+{
+    mProjectionMatrix = projection;
+    mProjectionMatrixDirty = false;
+}
+
+Eigen::MatrixP3f Camera::modelviewMatrix() const
+{
+    if (mModelviewMatrixDirty) {
+        const_cast<Camera*>(this)->recalculateModelviewMatrix();
+    }
+    return mModelviewMatrix;
+}
+
+Eigen::MatrixP3f Camera::projectionMatrix() const
+{
+    if (mProjectionMatrixDirty) {
+        const_cast<Camera*>(this)->recalculateProjectionMatrix();
+    }
+    return mProjectionMatrix;
+}
+
+
+}
--- trunk/playground/libs/kgllib/extras/kgllib/camera.h #782263:782264
@@ -22,6 +22,7 @@
 #include "kgllib.h"
 
 #include <eigen/vector.h>
+#include <eigen/projective.h>
 
 namespace KGLLib
 {
@@ -57,11 +58,26 @@
     Eigen::Vector3f lookAt() const  { return mLookAt; }
     Eigen::Vector3f up() const  { return mUp; }
 
+    void setModelviewMatrix(const Eigen::MatrixP3f& modelview);
+    void setProjectionMatrix(const Eigen::MatrixP3f& projection);
+
+    Eigen::MatrixP3f modelviewMatrix() const;
+    Eigen::MatrixP3f projectionMatrix() const;
+
 protected:
+    void recalculateModelviewMatrix();
+    void recalculateProjectionMatrix();
+
+protected:
     Eigen::Vector3f mPosition;
     Eigen::Vector3f mLookAt;
     Eigen::Vector3f mUp;
     float mFoV, mAspect, mDepthNear, mDepthFar;
+
+    Eigen::MatrixP3f mModelviewMatrix;
+    bool mModelviewMatrixDirty;
+    Eigen::MatrixP3f mProjectionMatrix;
+    bool mProjectionMatrixDirty;
 };
 
 }
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic