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

Implementing the target camera

The target camera works the opposite way. Rather than the position, the target remains fixed, while the camera moves or rotates around the target. Some operations like panning, move both the target and the camera position together.

Getting ready

The following figure shows an illustration of a target camera. Note that the small box is the target position for the camera.

The code for this recipe resides in the Chapter2/TargetCamera directory. The CTargetCamera class is defined in the Chapter2/src/TargetCamera.[h/cpp] files. The class declaration is as follows:

class CTargetCamera : public CAbstractCamera
{
public:
  CTargetCamera(void);
  ~CTargetCamera(void);
  void Update();
  void Rotate(const float yaw, const float pitch, const float roll);
  void SetTarget(const glm::vec3 tgt);
  const glm::vec3 GetTarget() const;
  void Pan(const float dx, const float dy);
  void Zoom(const float amount );
  void Move(const float dx, const float dz);
protected:
  glm::vec3 target;
  float minRy, maxRy;
  float distance;
  float minDistance, maxDistance;
};

How to do it…

We implement the target camera as follows:

  1. Define the CTargetCamera class with a target position (target), the rotation limits (minRy and maxRy), the distance between the target and the camera position (distance), and the distance limits (minDistance and maxDistance).
  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);
  3. Use the distance to get a vector and then translate this vector by the current rotation matrix:
    glm::vec3 T = glm::vec3(0,0,distance);
    T = glm::vec3(R*glm::vec4(T,0.0f));
  4. Get the new camera position by adding the translation vector to the target position:
    position = target + T;
  5. Recalculate the orthonormal basis and then the view matrix:
    look = glm::normalize(target-position);
    up = glm::vec3(R*glm::vec4(UP,0.0f));
    right = glm::cross(look, up);
    V = glm::lookAt(position, target, up);

There's more…

The Move function moves both the position and target by the same amount in both look and right vector directions.

void CTargetCamera::Move(const float dx, const float dy) {
  glm::vec3 X = right*dx;
  glm::vec3 Y = look*dy;
  position += X + Y;
  target += X + Y;
  Update();
}

The Pan function moves in the xy plane only, hence the up vector is used instead of the look vector:

void CTargetCamera::Pan(const float dx, const float dy) {
  glm::vec3 X = right*dx;
  glm::vec3 Y = up*dy;
  position += X + Y;
  target += X + Y;
  Update();
}

The Zoom function moves the position in the look direction:

void CTargetCamera::Zoom(const float amount) { 
  position += look * amount;
  distance = glm::distance(position, target); 
  Distance = std::max(minDistance, std::min(distance, maxDistance));
  Update();
}

The demonstration for this recipe renders an infinite checkered plane, as in the previous recipe, and is shown in the following figure:

See also

主站蜘蛛池模板: 博野县| 斗六市| 疏附县| 瑞安市| 兰考县| 玉林市| 双峰县| 绥宁县| 成安县| 乌苏市| 互助| 遵义县| 灵川县| 宁南县| 双牌县| 南京市| 泰顺县| 朔州市| 镇平县| 晋州市| 浦北县| 缙云县| 博客| 临沂市| 阳江市| 肇东市| 楚雄市| 义乌市| 洞口县| 留坝县| 铜梁县| 库尔勒市| 荆州市| 天峻县| 开原市| 百色市| 沾益县| 稷山县| 遂昌县| 甘泉县| 大埔区|