我正在研究OpenGL中的聚光灯变换系统。众所周知,聚光灯默认位置和锥形方向。但在我的实现中,它还必须具有旋转和方向。在这种情况下,旋转< / strong> - 方向时光锥的局部旋转 - 应用局部旋转后圆锥的世界旋转。
在这项工作中我遇到了各种轴翻转问题,部分原因是glm :: lookAt方法反转了输出矩阵的“眼”向量。现在一切都很好,除了我必须反转最终方向向量y和z部分是为了使聚光锥面不是反方向:
lookatMatr[2].y =- lookatMatr[2].y;
lookatMatr[2].z =- lookatMatr[2].z;
我无法弄清楚两件事:
1.如何做到这一点,以便我最后不需要进行反演。 2。为什么只需要Y轴和Z轴进行反演。
以下是转型的完整代码:
glm::vec4 worldPos = WorldMatr * _pos ;
glm::vec4 worldDir = WorldMatr * glm::vec4( _lightDir,1) ;
glm::vec4 worldUp = WorldMatr * glm::vec4(Y_AXIS,1) ;
//first construct lookat matrix to get direction vector
glm::mat4 lookatMatr = glm::lookAt(glm::vec3(worldPos),glm::vec3(worldDir),glm::vec3(worldUp)) ;
//rotate locally :
lookatMatr = glm::rotate(lookatMatr,30.0f,X_AXIS) ;
lookatMatr = glm::rotate(lookatMatr,0.0f,Y_AXIS) ;
lookatMatr = glm::rotate(lookatMatr,0.0f,Z_AXIS) ;
//Orient :
lookatMatr = Transform().GetOrientationMatrix() * ( lookatMatr );
_posOut= worldPos ;
// lookatMatr[2].x =- lookatMatr[2].x;//why only Y and Z to be inverted?
lookatMatr[2].y =- lookatMatr[2].y;
lookatMatr[2].z =- lookatMatr[2].z;
_dirOut= ( lookatMatr[2]) ;
更新
好的,正如下面的建议,我将_lightDir的一部分设置为零,现在这样做:
_dirOut=World * Transform().GetOrientationMatrix() * rotMatr * glm::vec4( _lightDir,0);
它正确显示光锥,但其方向现在在X轴上翻转。
答案 0 :(得分:1)
你必须记住的一件事是lookAt
产生一个倒置矩阵。该矩阵是将矢量从世界空间转换到相机空间的系统变换。这等于将相机从其在世界空间中的位置移动到原点的模型转换。反之亦然。
描述路线的矢量必须在其w分量中为0。这导致跳过矩阵的平移部分。更正worldDir
和worldUp
的定义。
但是,你真的不需要外观矩阵。相反,您应该只使用worldDir
并对此向量执行转换。所以整体方向是:
_dirOut =
WorldMatr * OrientationMatrix * LocalRotationMatrix * glm::vec4(_lightDir, 0);
您可以预乘矩阵,然后对矢量执行一次变换,也可以将矢量变换三次(首先使用LocalRotationMatrix等等)。