由世界坐标系转换到摄像机坐标系的lookAt()函数
juteman 人气:0在学习图形学和opengl的时候,都涉及到坐标转化,从物体坐标转换为世界的坐标,从世界的坐标转换为摄像机的坐标。
在世界坐标到摄像机转换的过程中常用lookAt函数得到转化矩阵。GLM官方文档对它的解释是:
1 detail::tmat4x4<T> glm::gtc::matrix_transform::lookAt 2 ( 3 detail::tvec3< T > const & eye, 4 detail::tvec3< T > const & center, 5 detail::tvec3< T > const & up 6 )
前面两个参数都比较好理解,eye代表了摄像机在世界坐标系的坐标,center是观察点,通过center-eye可以得到观察向量,通过glm::perspective可以设置视角。
那么up呢?up代表的什么意思,大多文档都说这个参数一般值是(0,1,0)如果要倒着看就是(0,-1,0)。stackoverflow上给出的的答案是:
- The
up
vector is basically a vector defining your world's "upwards" direction. In almost all normal cases, this will be the vector(0, 1, 0)
i.e. towards positive Y.
对此我做了个测试,对于opengl画一个最简单的三角形,设置录像机参数
glm::mat4 View = glm::lookAt( glm::vec3(0, 0, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0) );
此时摄像机正向观察三角形
,得到的三角形观察是接着我设置lookAt参数一个很离谱的参数
glm::mat4 View = glm::lookAt(glm::vec3(0, 0, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 100));
得到与上图对比结果:
我的肉眼看不出区别,也就是没有区别。
按照stackoverflow的解释,up代表世界坐标的上方向。但是这里我的方向都偏到Z轴去了,而三角形完全没有变化。也就是stackoverflow给出的是错误答案
研究了一下lookAt的实现,如下:
template<typename T, qualifier Q> GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtRH(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up) { vec<3, T, Q> const f(normalize(center - eye)); vec<3, T, Q> const s(normalize(cross(f, up))); vec<3, T, Q> const u(cross(s, f)); mat<4, 4, T, Q> 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; }
通过这段源码可以得到,lookAt重新定义了摄像机坐标系。我们知道空间垂直坐标系有3条轴,第一条就是center - eye也就是摄像机观察制定点的向量,这里可以把他当做Z轴。第二条轴就是f,和up的×值。也就是说up代表的根本不是什么世界正上方而是一条”辅助向量",通过这个辅助向量能得到摄像机的坐标系的X轴。而当up(0,1,0)时摄像机转角正好为0。已知x轴和z轴自然能得出y轴,这样就定义了摄像机坐标轴。
也就是说up是一条辅助向量,它确实能控制摄像机的旋转方向,他与center - eye共同控制了摄像机的旋转面
加载全部内容