0

我正在研究 OpenGL 中的聚光灯变换系统。众所周知,聚光灯默认具有位置和锥方向。但在我的实现中,它还必须具有旋转和方向。在这种情况下,旋转- 光锥的局部旋转,而方向- 应用局部旋转后圆锥的世界旋转。

我在这项工作中遇到了各种轴翻转问题,部分原因是 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 的 w 部分设置为零,现在这样做:

_dirOut=World * Transform().GetOrientationMatrix() *  rotMatr *   glm::vec4( _lightDir,0);

它正确显示了光锥,但它的方向现在在 X 轴上翻转了。

4

1 回答 1

1

你必须记住的一件事是lookAt产生一个倒置矩阵。该矩阵是将向量从世界空间转换到相机空间的系统变换。这等于将相机从其在世界空间中的位置移动到原点的模型转换。反之亦然。

描述方向的向量必须在其 w 分量中有一个 0。这导致跳过矩阵的转换部分。更正您对worldDir和的定义worldUp

但是,您真的不需要 lookAt 矩阵。相反,您应该只worldDir对这个向量进行转换。所以总体方向是:

_dirOut = 
    WorldMatr * OrientationMatrix * LocalRotationMatrix * glm::vec4(_lightDir, 0);

您可以对矩阵进行预乘,然后对向量执行一次变换,也可以对向量进行三次变换(首先使用 LocalRotationMatrix 等)。

于 2013-04-17T13:10:56.647 回答