官术网_书友最值得收藏!

Implementing the free camera

Free camera is the first camera type which we will implement in this recipe. A free camera does not have a fixed target. However it does have a fixed position from which it can look in any direction.

Getting ready

The following figure shows a free viewing camera. When we rotate the camera, it rotates at its position. When we move the camera, it keeps looking in the same direction.

The source code for this recipe is in the Chapter2/FreeCamera directory. The CFreeCamera class is defined in the Chapter2/src/FreeCamera.[h/cpp] files. The class interface is as follows:

class CFreeCamera : public CAbstractCamera
{
public:
  CFreeCamera(void);
  ~CFreeCamera(void);
  void Update();
  void Walk(const float dt);
  void Strafe(const float dt);
  void Lift(const float dt);
  void SetTranslation(const glm::vec3& t);
  glm::vec3 GetTranslation() const;
  void SetSpeed(const float speed);
  const float GetSpeed() const;
protected:
  float speed; //move speed of camera in m/s
  glm::vec3 translation;
};

How to do it…

The steps needed to implement the free camera are as follows:

  1. Define the CFreeCamera class and add a vector to store the current translation.
  2. In the Update method, calculate the new orientation (rotation) matrix, using the current camera orientations (that is, yaw, pitch, and roll amount):
    glm::mat4 R = glm::yawPitchRoll(yaw,pitch,roll);
    Note

    Make sure that the yaw, pitch, and roll angles are in radians.

  3. Translate the camera position by the translation amount:
    position+=translation;

    If we need to implement a free camera which gradually comes to a halt, we should gradually decay the translation vector by adding the following code after the key events are handled:

    glm::vec3 t = cam.GetTranslation();
    if(glm::dot(t,t)>EPSILON2) {
       cam.SetTranslation(t*0.95f); 
    }

    If no decay is needed, then we should clear the translation vector to 0 in the CFreeCamera::Update function after translating the position:

    translation = glm::vec3(0);
  4. Transform the look vector by the current rotation matrix, and determine the right and up vectors to calculate the orthonormal basis:
    look = glm::vec3(R*glm::vec4(0,0,1,0));
    up = glm::vec3(R*glm::vec4(0,1,0,0));
    right = glm::cross(look, up);
  5. Determine the camera target point:
    glm::vec3 tgt = position+look;
  6. Use the glm::lookat function to calculate the new view matrix using the camera position, target, and the up vector:
    V = glm::lookAt(position, tgt, up); 

There's more…

The Walk function simply translates the camera in the look direction:

void CFreeCamera::Walk(const float dt) {
  translation += (look*dt);
}

The Strafe function translates the camera in the right direction:

void CFreeCamera::Strafe(const float dt) {
  translation += (right*dt);
}

The Lift function translates the camera in the up direction:

void CFreeCamera::Lift(const float dt) {
  translation += (up*dt);
}

Running the demo application renders an infinite checkered plane as shown in the following figure. The free camera can be moved around by pressing the keys W, S, A, D, Q, and Z. Left-clicking the mouse rotates the camera at the current position to change the look direction. Middle-click zooms the camera in the look direction.

See also

主站蜘蛛池模板: 扎赉特旗| 阿拉善右旗| 静海县| 梅河口市| 上高县| 增城市| 巧家县| 连州市| 福泉市| 临夏市| 东源县| 海兴县| 湄潭县| 石棉县| 抚顺县| 青河县| 高青县| 峡江县| 兴安盟| 沅江市| 通州区| 青神县| 塘沽区| 苍南县| 惠水县| 丹凤县| 丰镇市| 岱山县| 兴安县| 潞西市| 乌鲁木齐市| 松原市| 新乐市| 青河县| 台北市| 昭觉县| 清水县| 黎城县| 齐齐哈尔市| 沁阳市| 茌平县|