Montag, 12. Dezember 2011

A camera in 3D space ···Part 2···

I made an improvement to my camera:
it can now behave first-person like. You can toggle between those modes.



The up-vector is fixed now. It always points up (x = 0.0f, y, z = 0.0f).
The point where I look at must be between total up and total down, between 0° and 180°. I've shrunken those values to 1° and 179° just in case.
Also moving forward (& backward & sidewards) is now independent from looking up and down. So moving is done on a x-z-plane. But it is also possible to move up and down along the y-axis.

Now here is the diff to the last version
(with more colors and stuff: http://paste.kde.org/158054/ ):
diff -r 3a7c5fbb7941 source/ccamera.cpp
--- a/source/ccamera.cpp    Thu Dec 08 23:15:14 2011 +0100
+++ b/source/ccamera.cpp    Mon Dec 12 11:17:38 2011 +0100
@@ -24,24 +24,6 @@
 #include "headers_with_gcc_warnings/aiScene.h"
 #include "aiToGLM.cpp"

-CCamera::CCamera():
- m_logError(),
- m_viewMatrix( 1.0f),
- m_modelMatrix( 1.0f),
- m_projectionMatrix( 1.0f),
- m_projectionViewMatrix( 1.0f),
- m_eyeGlobal( glm::vec3(1.0f, 0.0f, 0.0f)),
- m_centerGlobal( glm::vec3(0.0f, 0.0f, 0.0f)),
- m_upGlobal( glm::vec3(0.0f, 1.0f, 0.0f)),
- m_xGlob(0),
- m_yGlob(0),
- m_zGlob(0),
- m_camera( nullptr),
- m_ID( 0)
-{
-    m_modelMatrix = glm::translate( m_modelMatrix, glm::vec3( 0.0f, 0.0f, -1.0f));
-}
-
 CCamera::CCamera(uint64_t id, aiCamera* camera):
  m_logError(),
  m_viewMatrix( 1.0f),
@@ -55,7 +37,14 @@
  m_yGlob(0),
  m_zGlob(0),
  m_camera( camera),
- m_ID(id)
+ m_ID(id),
+ m_currentMode(FLY),
+ m_pitchAngleFPSMode(0.0f),
+ m_translate(nullptr),
+ m_pitch(nullptr),
+ m_yaw(nullptr),
+ m_roll(nullptr),
+ m_updateAxis(nullptr)
 {
    
 }
@@ -66,32 +55,12 @@

 void CCamera::translate(glm::core::type::vec3& translateVector)
 {
-    glm::vec3 l_z = translateVector.z*glm::normalize(m_zGlob);
-    glm::vec3 l_y = translateVector.y*glm::normalize(m_yGlob);
-    glm::vec3 l_x = translateVector.x*glm::normalize(m_xGlob);
-   
-    glm::vec3 t0 = l_z + l_y + l_x;
-   
-    m_eyeGlobal += t0;
-    m_centerGlobal += t0;
-   
-    updateViewMatrix();
-    updateAxis();
+    m_translate( this, glm::vec3(translateVector));
 }

 void CCamera::translate(glm::core::type::vec3&& translateVector)
 {
-    glm::vec3 l_z = translateVector.z*glm::normalize(m_zGlob);
-    glm::vec3 l_y = translateVector.y*glm::normalize(m_yGlob);
-    glm::vec3 l_x = translateVector.x*glm::normalize(m_xGlob);
-   
-    glm::vec3 t0 = l_z + l_y + l_x;
-   
-    m_eyeGlobal += t0;
-    m_centerGlobal += t0;
-   
-    updateViewMatrix();
-    updateAxis();
+    m_translate( this, std::move( translateVector));
 }

 void CCamera::updateViewMatrix()
@@ -174,7 +143,8 @@
     m4 = aim * (myNode->mTransformation * m4);
    
     m_modelMatrix = aiToGLMM4(m4);
-    print(m_modelMatrix, m_logError.logStream());
+
+    switchToFLYMode();
    
     updateGlobals();
     updateAxis();
@@ -196,9 +166,7 @@

 void CCamera::updateAxis()
 {
-    m_yGlob = m_upGlobal;
-    m_zGlob = m_centerGlobal - m_eyeGlobal;
-    m_xGlob = glm::cross(m_yGlob, m_zGlob);
+    m_updateAxis( this);
 }

 // TODO: use quaternions for rotation (but works already fine)
@@ -225,13 +193,50 @@

 void CCamera::roll(float angle) // local z
 {
-    glm::vec3 diffRotZ = glm::rotate( m_yGlob, angle, m_zGlob) - m_yGlob;
-    m_upGlobal += diffRotZ;
+    m_roll( this, angle);
+}
+
+void CCamera::pitch(float angle) // local X
+{
+    m_pitch( this, angle);
+}
+
+void CCamera::yaw(float angle) // local Y (up)
+{
+    m_yaw( this, angle);
+}
+
+void CCamera::translateFLYMode(glm::core::type::vec3&& translateVector)
+{
+    glm::vec3 l_z = translateVector.z*glm::normalize(m_zGlob);
+    glm::vec3 l_y = translateVector.y*glm::normalize(m_yGlob);
+    glm::vec3 l_x = translateVector.x*glm::normalize(m_xGlob);
+   
+    glm::vec3 t0 = l_z + l_y + l_x;
+   
+    m_eyeGlobal += t0;
+    m_centerGlobal += t0;
+   
     updateViewMatrix();
     updateAxis();
 }

-void CCamera::pitch(float angle) // local X
+void CCamera::translateFPSMode(glm::core::type::vec3&& translateVector)
+{
+    glm::vec3 l_z = translateVector.z*glm::normalize( glm::vec3(m_zGlob.x, 0.0f, m_zGlob.z));
+    glm::vec3 l_y = translateVector.y*glm::normalize(m_yGlob);
+    glm::vec3 l_x = translateVector.x*glm::normalize(m_xGlob);
+   
+    glm::vec3 t0 = l_z + l_y + l_x;
+   
+    m_eyeGlobal += t0;
+    m_centerGlobal += t0;
+   
+    updateViewMatrix();
+    updateAxis();
+}
+
+void CCamera::pitchFLYMode(float angle)
 {
     glm::vec3 diffCenter = glm::rotate( m_zGlob, -angle, m_xGlob) - m_zGlob;
     glm::vec3 diffUp = glm::rotate( m_yGlob, -angle, m_xGlob) - m_yGlob;
@@ -241,10 +246,102 @@
     updateAxis();
 }

-void CCamera::yaw(float angle) // local Y (up)
+void CCamera::pitchFPSMode(float angle)
+{   
+    if( m_pitchAngleFPSMode + angle <  179.0f && m_pitchAngleFPSMode + angle > 1.0f){
+        m_pitchAngleFPSMode += angle;
+        glm::vec3 diffCenter = glm::rotate( m_centerGlobal-m_eyeGlobal, -angle, m_xGlob) - (m_centerGlobal-m_eyeGlobal);
+        m_centerGlobal += diffCenter;
+        updateViewMatrix();
+        updateAxis();
+    }
+}
+
+void CCamera::rollFLYMode(float angle)
+{
+    glm::vec3 diffRotZ = glm::rotate( m_yGlob, angle, m_zGlob) - m_yGlob;
+    m_upGlobal += diffRotZ;
+    updateViewMatrix();
+    updateAxis();
+}
+
+void CCamera::rollFPSMode(float angle)
+{
+    // no rolling in FPS mode
+}
+
+void CCamera::yawFLYMode(float angle)
 {
     glm::vec3 diffLR = glm::rotate( m_zGlob, -angle, m_yGlob) - m_zGlob;
     m_centerGlobal += diffLR;
     updateViewMatrix();
     updateAxis();
 }
+
+void CCamera::yawFPSMode(float angle)
+{
+    m_centerGlobal += glm::rotate( m_zGlob, -angle, m_yGlob) - m_zGlob;
+    updateViewMatrix();
+    updateAxis();
+}
+
+void CCamera::updateAxisFLYMode()
+{
+    m_yGlob = m_upGlobal;
+    m_zGlob = m_centerGlobal - m_eyeGlobal;
+    m_xGlob = glm::cross(m_yGlob, m_zGlob);
+}
+
+void CCamera::updateAxisFPSMode()
+{
+    m_yGlob = glm::vec3( 0.0f, std::abs(m_upGlobal.y), 0.0f);
+    m_zGlob = m_centerGlobal - m_eyeGlobal;
+    m_xGlob = glm::cross(m_yGlob, m_zGlob);
+}
+
+void CCamera::toggleCameraMode()
+{
+    switch( m_currentMode){
+        case FLY:
+            m_logError.logStream() << "Changing mode to: FPS\n";
+            switchToFPSMode();
+            break;
+        case FPS:
+            m_logError.logStream() << "Changing mode to: FLY\n";
+            switchToFLYMode();
+            break;
+        default:
+            break;
+    };
+}
+
+void CCamera::switchToFLYMode()
+{
+    m_currentMode = FLY;
+    m_translate = &CCamera::translateFLYMode;
+    m_pitch = &CCamera::pitchFLYMode;
+    m_yaw = &CCamera::yawFLYMode;
+    m_roll = &CCamera::rollFLYMode;
+    m_updateAxis = &CCamera::updateAxisFLYMode;
+   
+    m_updateAxis(this);
+}
+
+void CCamera::switchToFPSMode()
+{
+    m_currentMode = FPS;
+    m_translate = &CCamera::translateFPSMode;
+    m_pitch = &CCamera::pitchFPSMode;
+    m_yaw = &CCamera::yawFPSMode;
+    m_roll = &CCamera::rollFPSMode;
+    m_updateAxis = &CCamera::updateAxisFPSMode;
+   
+    m_yGlob = glm::vec3( 0.0f, std::abs(m_yGlob.y), 0.0f);
+    m_upGlobal = glm::vec3( 0.0f, std::abs(m_upGlobal.y), 0.0f);
+   
+   
+    m_updateAxis(this);
+   
+    glm::vec3 lookAt = m_centerGlobal-m_eyeGlobal;
+    m_pitchAngleFPSMode = 180 - glm::degrees( std::acos(glm::dot( lookAt, m_yGlob) / ( glm::length(lookAt) * glm::length(m_yGlob))));
+}
diff -r 3a7c5fbb7941 source/ccamera.h
--- a/source/ccamera.h    Thu Dec 08 23:15:14 2011 +0100
+++ b/source/ccamera.h    Mon Dec 12 11:17:38 2011 +0100
@@ -28,10 +28,11 @@

 class aiNode;
 struct aiCamera;
+
 class CCamera {
-
 public:
-    CCamera();
+    enum Mode { FLY = 0, FPS};
+public:
     CCamera( const CCamera&);
     void operator=( const CCamera&);
     CCamera( uint64_t id, aiCamera* camera);
@@ -55,6 +56,8 @@
     void pitchYawRoll( glm::vec3& pyaAngles);
     void pitchYawRoll( glm::vec3&& pyaAngles);
    
+    void toggleCameraMode();
+   
 private:
     CLogErrorStream m_logError;
     // The view matrix, which can also be known as the world matrix determines the position of the ‘camera’ in space.
@@ -73,9 +76,38 @@
     aiCamera* m_camera;
     uint64_t m_ID;
    
+    Mode m_currentMode;
+   
+    float m_pitchAngleFPSMode;
+   
+    std::function<void(CCamera*, glm::vec3&&)> m_translate;
+    std::function<void(CCamera*, float)> m_pitch;
+    std::function<void(CCamera*, float)> m_yaw;
+    std::function<void(CCamera*, float)> m_roll;
+    std::function<void(CCamera*)> m_updateAxis;
+   
     void updateViewMatrix();
     void updateGlobals();
     void updateAxis();
+   
+    void switchToFLYMode();
+    void switchToFPSMode();
+   
+    void translateFLYMode( glm::vec3&& translateVector);
+    void translateFPSMode( glm::vec3&& translateVector);
+   
+    void pitchFLYMode( float angle);
+    void pitchFPSMode( float angle);
+   
+    void yawFLYMode( float angle);
+    void yawFPSMode( float angle);
+   
+    void rollFLYMode( float angle);
+    void rollFPSMode( float angle);
+   
+    void updateAxisFLYMode();
+    void updateAxisFPSMode();
+   
 };

 #endif // CCAMERA_H