zoukankan      html  css  js  c++  java
  • opengl 教程(13) 摄像机坐标系

    原帖地址:http://ogldev.atspace.co.uk/www/tutorial13/tutorial13.html

          在前面的教程中,我们都是默认摄像机坐标在三维坐标的原点,本篇教程我们开始讨论把摄像机放在三维空间的任意位置,从而更方便的从不同视角观察物体。决定三维空间摄像机坐标系有三个因素,摄像机的在三维空间的位置,摄像机lookat的方向向量,摄像机的up方向向量,有了这三个值,我们就可以确定三维空间摄像机的位置和方位,从而推导出世界坐标系到摄像机坐标的转化矩阵。

    具体推导见我转的另外一篇文章:http://www.cnblogs.com/mikewolf2002/archive/2012/11/25/2787636.html

    主要代码变化:

     

    建立一个矩阵类Matrix4f,用来管理所有的矩阵操作。

    pipeline.h

    struct {
    Vector3f Pos;
    Vector3f Target;
    Vector3f Up;
    } m_camera;

    math3d.h

    Vector3f Vector3f::Cross(const Vector3f& v) const
    {
    const float _x = y * v.z - z * v.y;
    const float _y = z * v.x - x * v.z;
    const float _z = x * v.y - y * v.x;
    return Vector3f(_x, _y, _z);
    }

    向量类Vector3f增加了2个向量叉积的函数。

    math3d.h

    Vector3f& Vector3f::Normalize()
    {
    const float Length = sqrtf(x * x + y * y + z * z);
    x /= Length;
    y /= Length;
    z /= Length;
    return *this;
    }

    注意:右向量是根据叉积算出来的。

    math3d.cpp

    void Matrix4f::InitCameraTransform(const Vector3f& Target, const Vector3f& Up)
    {
    Vector3f N = Target;
    N.Normalize();
    Vector3f U = Up;
    U.Normalize();
    U = U.Cross(Target);
    Vector3f V = N.Cross(U);
    m[0][0] = U.x; m[0][1] = U.y; m[0][2] = U.z; m[0][3] = 0.0f;
    m[1][0] = V.x; m[1][1] = V.y; m[1][2] = V.z; m[1][3] = 0.0f;
    m[2][0] = N.x; m[2][1] = N.y; m[2][2] = N.z; m[2][3] = 0.0f;
    m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f;
    }

    pipeline.cpp

     

    const Matrix4f* Pipeline::GetTrans()
    {
    Matrix4f ScaleTrans, RotateTrans, TranslationTrans, CameraTranslationTrans, CameraRotateTrans, PersProjTrans;
    ScaleTrans.InitScaleTransform(m_scale.x, m_scale.y, m_scale.z);
    RotateTrans.InitRotateTransform(m_rotateInfo.x, m_rotateInfo.y, m_rotateInfo.z);
    TranslationTrans.InitTranslationTransform(m_worldPos.x, m_worldPos.y, m_worldPos.z);
    CameraTranslationTrans.InitTranslationTransform(-m_camera.Pos.x, -m_camera.Pos.y, -m_camera.Pos.z);
    CameraRotateTrans.InitCameraTransform(m_camera.Target, m_camera.Up);
    PersProjTrans.InitPersProjTransform(m_persProj.FOV, m_persProj.Width, m_persProj.Height, m_persProj.zNear, m_persProj.zFar);
    m_transformation = PersProjTrans * CameraRotateTrans * CameraTranslationTrans * TranslationTrans * RotateTrans * ScaleTrans;
    return &m_transformation;
    }

          下面代码把摄像机从原点移动到(1.0,1.0,-3.0)的位置,摄像机对准位置(0.45f, 0.0f, 1.0f),摄像机的up方向是y轴正方向。

    tutorial13.cpp

    Vector3f CameraPos(1.0f, 1.0f, -3.0f);
    Vector3f CameraTarget(0.45f, 0.0f, 1.0f);
    Vector3f CameraUp(0.0f, 1.0f, 0.0f);
    p.SetCamera(CameraPos, CameraTarget, CameraUp);

     

    程序运行后界面如下:

    image

  • 相关阅读:
    SSH公/私秘钥的生成及使用
    使用docker-compose部署Kafka集群
    使用docker或者docker-compose部署Zookeeper集群
    zookeeper相关概念
    redis相关概念
    mq-rabbitmq
    mysql事务隔离级别
    新自动化测试框架+微信机器人构建思路
    当eclipse调用tomcat的时候发生了什么?
    .net 获取配置项
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/2861796.html
Copyright © 2011-2022 走看看