Matrix 旋转对象时法线的旋转方向错误

Matrix 旋转对象时法线的旋转方向错误,matrix,3d,webgl,quaternions,gl-matrix,Matrix,3d,Webgl,Quaternions,Gl Matrix,我正在WebGL中渲染一个简单的圆环体。旋转顶点效果很好,但法线有问题。当绕一个轴旋转时,法线保持正确的方向,但当绕第二个轴旋转增加时,法线开始以错误的方式向上旋转,直到其中一个旋转为180°,然后法线以完全相反的方向旋转。 我假设问题在于用于旋转的四元数,但我还不能确定什么是错误的 下面是我的项目的一个(稍加修改,但仍然显示了问题)JSFIDLE: 在fiddle的html部分有一个div,其中包含我正在读取的用于生成圆环体的obj文件中的所有数据(尽管分辨率较低) 顶点着色器: attrib

我正在WebGL中渲染一个简单的圆环体。旋转顶点效果很好,但法线有问题。当绕一个轴旋转时,法线保持正确的方向,但当绕第二个轴旋转增加时,法线开始以错误的方式向上旋转,直到其中一个旋转为180°,然后法线以完全相反的方向旋转。 我假设问题在于用于旋转的四元数,但我还不能确定什么是错误的

下面是我的项目的一个(稍加修改,但仍然显示了问题)JSFIDLE:
在fiddle的html部分有一个div,其中包含我正在读取的用于生成圆环体的obj文件中的所有数据(尽管分辨率较低)

顶点着色器:

attribute vec4 aVertexPosition;
attribute vec3 aNormalDirection;

uniform mat4 uMVPMatrix;
uniform mat3 uNMatrix;

varying vec3 nrm;

void main(void) {
    gl_Position = uMVPMatrix * aVertexPosition;
    nrm = aNormalDirection * uNMatrix;
}
片段着色器:

varying vec3 nrm;

void main(void) {
    gl_FragColor = vec4(nrm, 1.0);
}
更新矩阵(有输入时运行):

创建旋转四元数(移动鼠标时调用):

仅围绕Y轴旋转圆环体,法线指向正确的方向:

围绕两个轴旋转圆环体。法线指向整个位置:

我使用v2.3.2进行所有矩阵和四元数运算

更新: 似乎仅围绕Z轴旋转(通过将
quat.setAxisAngle
的输入轴显式设置为
[0,0,1]
,或使用
quat.rotateZ
)也会导致法线向相反方向旋转。
轴的z分量归零没有帮助

更新2: 按
quat.rotateX(q,q,l*刻度)旋转;四旋转(q,q,l*刻度);四乘(旋转,q,旋转)似乎是正确的,但一旦引入围绕Z的旋转,Z法线就开始四处移动。
使用x或y鼠标值中的差异而不是
l
会导致所有法线移动,因此对x和y使用差异很大的
scale
-值也是如此


更新3:将着色器中的乘法顺序更改为
uNMatrix*aNormalDirection
会导致法线始终以错误的方式旋转。

在我的例子中,问题在于如何从.obj文件加载数据。我已反转了所有顶点的z位置,但法线是从非反转顶点生成的。

使用非反转z位置和翻转法线矩阵乘法解决了问题。

它不应该是
uNMatrix*aNormalDirection在你的片段着色器中?@WacławJasper我也这么认为,但在读了一点之后,似乎有些人将法线矩阵放在左边,这取决于它是如何创建的。无论如何,改变顺序会导致法线的每次旋转都被反转。这可能意味着其中一个符号被翻转到了某个地方。也许您的
normalDirection
指向了错误的方向?或者,将模型视图矩阵传递给顶点着色器,并将法线矩阵计算为
转置(反转(模型视图))
以查看其是否有效?或者发布一个完整的可运行示例,我可以看一看。我尝试翻转法线,并从模型视图计算法线矩阵。早上我会发布一些可运行的代码。@WacławJasper现在有一个到JSfiddle的链接
mat4.perspective(pMatrix, Math.PI*0.25, width/height, clipNear, clipFar); //This is actually not run on input, it is just here to show the creation of the perspective matrix
mat4.fromRotationTranslation(mvMatrix, rotation, position);
mat3.normalFromMat4(nMatrix, mvMatrix);

mat4.multiply(mvpMatrix, pMatrix, mvMatrix);

var uMVPMatrix = gl.getUniformLocation(shaderProgram, "uMVPMatrix");
var uNMatrix = gl.getUniformLocation(shaderProgram, "uNMatrix");
gl.uniformMatrix4fv(uMVPMatrix, false, mvpMatrix);
gl.uniformMatrix3fv(uNMatrix, false, nMatrix);
var d = vec3.fromValues(lastmousex-mousex, mousey-lastmousey, 0.0);
var l = vec3.length(d);
vec3.normalize(d,d);
var axis = vec3.cross(vec3.create(), d, [0,0,1]);
vec3.normalize(axis, axis);

var q = quat.setAxisAngle(quat.create(), a, l*scale);
quat.multiply(rotation, q, rotation);