openGL坐标研究

论坛 期权论坛 脚本     
匿名网站用户   2020-12-20 02:45   21   0

左右手坐标系: http://www.realtimerendering.com/blog/tag/coordinates/
openGL坐标系: http://blog.csdn.net/meegomeego/article/details/8686816

这边文章将我自己慢慢探索这个问题的过程记述下来。

openGL世界坐标系

首先,模型数据:从max里新建一个plane,如图
这里写图片描述
导出为obj(因为能看到里面的坐标,fbx不好看):
这里写图片描述
如果在导出obj时勾选flipYz:
这里写图片描述
也就是:
这里写图片描述
然后我们放在openGL里面,其中模型的导入用的assimp库,

void loadModel(string const &path)
    {
        //read file via ASSIMP
        Assimp::Importer importer;
        const aiScene *scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
        if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
        {
            cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl;
            return;
        }

        directory = path.substr(0, path.find_last_of('/'));
        processNode(scene->mRootNode, scene);
    }

坐标系转换代码如下:

//shader.use();
        glm::mat4 projection = glm::perspective(glm::radians(mCamera->Zoom), (float)mW / (float)mH, 0.1f, 100.0f);
        glm::mat4 view = mCamera->GetCameraMatrix();

        //render the loaded model
        glm::mat4 model = glm::mat4();
        //model = glm::translate(model, glm::vec3(0.0f, -1.75f, 0.0f));
        model = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f));
        grass.SetMats(model, view, projection);

运行,没有flip的模型得到的窗口如下,与max里看到的图像相比,相当于max里图形绕x轴旋转90度:
这里写图片描述
flip的模型得到的窗口如下:
这里写图片描述
由于y为0,需要移动摄像机才能看到平面,否则看不到。
为了确定轴向,在3ds max里修改模型,如图:
这里写图片描述
这张图可以看出z轴朝外。
这里写图片描述
这张图看出y轴朝向
这里写图片描述
所以,openGL的世界坐标系轴向如图所示,为右手坐标系:
这里写图片描述

openGL之摄像机坐标系

camera的代码如下:

Camera(glm::vec3 pos = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f)) :
        Front(glm::vec3(0.0f, 0.0f, -1.0f)), Yaw(YAW),
        Pitch(PITCH), Zoom(ZOOM), Sensitivity(SENSITIVITY), CameraSpeed(CAMERASPEED)
    {
        Position = pos;
        WorldUp = up;
        UpdateCameraData();
    }

Front为(0, 0, -1),摄像机看向z轴的负方向。他们用的坐标轴是右手坐标系,比如,你右手边是正x轴,你是头上是正y轴,你面向屏幕,屏幕在坐标原点,正z轴从屏幕向外指向你。
那么,摄像机坐标是(0, 0, 3),摄像机指向是(0,0,-1)方向。up方向为(0,1,0),向上。
这里写图片描述
我们要得到摄像机坐标系,

输入摄像机位置
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
摄像机目标
glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);

我们知道摄像机指向z轴的负方向,所以交换cameraPos和cameraTarget方向,得到z轴正方向。

右轴:为了获取右轴,我们用一个小技巧,指定一个向上的向量up,up和z轴正向叉乘,得到x轴正向即右轴方向。
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); 
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));
up轴,将z轴正向和右轴叉乘得到up轴

glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);

通过上面这些向量,用lookAt函数得到view矩阵:
template <typename T, precision P>
    GLM_FUNC_QUALIFIER tmat4x4<T, P> lookAt(tvec3<T, P> const & eye, tvec3<T, P> const & center, tvec3<T, P> const & up)
    {
#       if GLM_COORDINATE_SYSTEM == GLM_LEFT_HANDED
            return lookAtLH(eye, center, up);
#       else
            return lookAtRH(eye, center, up);
#       endif
    }

    template <typename T, precision P>
    GLM_FUNC_QUALIFIER tmat4x4<T, P> lookAtRH
    (
        tvec3<T, P> const & eye,
        tvec3<T, P> const & center,
        tvec3<T, P> const & up
    )
    {
        tvec3<T, P> const f(normalize(center - eye));//-z
        tvec3<T, P> const s(normalize(cross(f, up))); // +x
        tvec3<T, P> const u(cross(s, f)); //+y

        tmat4x4<T, P> Result(1);
        Result[0][0] = s.x;
        Result[1][0] = s.y;
        Result[2][0] = s.z; //第一列+x
        Result[0][1] = u.x;
        Result[1][1] = u.y;
        Result[2][1] = u.z; //第二列+y
        Result[0][2] =-f.x;
        Result[1][2] =-f.y;
        Result[2][2] =-f.z; //第三列+z
        Result[3][0] =-dot(s, eye);
        Result[3][1] =-dot(u, eye);
        Result[3][2] = dot(f, eye);
        return Result;
    }

    template <typename T, precision P>
    GLM_FUNC_QUALIFIER tmat4x4<T, P> lookAtLH
    (
        tvec3<T, P> const & eye,
        tvec3<T, P> const & center,
        tvec3<T, P> const & up
    )
    {
        tvec3<T, P> const f(normalize(center - eye));
        tvec3<T, P> const s(normalize(cross(up, f)));
        tvec3<T, P> const u(cross(f, s));

        tmat4x4<T, P> Result(1);
        Result[0][0] = s.x;
        Result[1][0] = s.y;
        Result[2][0] = s.z;
        Result[0][1] = u.x;
        Result[1][1] = u.y;
        Result[2][1] = u.z;
        Result[0][2] = f.x;
        Result[1][2] = f.y;
        Result[2][2] = f.z;
        Result[3][0] = -dot(s, eye);
        Result[3][1] = -dot(u, eye);
        Result[3][2] = -dot(f, eye);
        return Result;
    }

坐标系转换矩阵第一列是+x轴的xyz,第二列是+y轴的xyz,第三列是+z轴的xyz。第四行的xyz元素是摄像机的坐标。

矩阵乘法转换坐标系

这里写图片描述
这里写图片描述
所以上面,知道了转换后的摄像机坐标系的xyz轴,就可以得到转换矩阵,转换矩阵也是求出的摄像机的xyz轴构造的。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP