Tim*_*Tim 31 android opengl-es linear-algebra
在帮助其他用户提出有关响应触摸事件 Android教程的问题之后,我下载了源代码,并且对我所看到的内容感到非常困惑.该教程似乎无法决定是否要使用行向量或列向量,它看起来都混淆了我.
在Android Matrix页面上,他们声称他们的约定是列向量/列主要,这是OpenGL的典型.
我是对的,还是我缺少的东西?以下是它的相关部分:
首先通过乘以mProjMatrix*mVMatrix创建MVPMatrix.到现在为止还挺好.
// Set the camera position (View matrix)
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0)
Run Code Online (Sandbox Code Playgroud)
接下来他们在MVPMatrix的左侧附加一个旋转?这看起来有点奇怪.
// Create a rotation for the triangle
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
// Combine the rotation matrix with the projection and camera view
Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0)
Run Code Online (Sandbox Code Playgroud)
以非转置顺序上传.
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
Run Code Online (Sandbox Code Playgroud)
最后在他们的着色器中,向量*矩阵乘法?
// the matrix must be included as a modifier of gl_Position
" gl_Position = vPosition * uMVPMatrix;"
Run Code Online (Sandbox Code Playgroud)
将这一切加在一起,我们得到:
gl_Position = vPosition * mRotation * mProjection * mView;
Run Code Online (Sandbox Code Playgroud)
在我的想象力中,这是不正确的.有什么解释我没看到这里发生了什么?
Joe*_*dez 26
作为编写OpenGL教程的人,我可以确认示例代码是不正确的.具体来说,着色器代码中的因子顺序应该相反:
" gl_Position = uMVPMatrix * vPosition;"
Run Code Online (Sandbox Code Playgroud)
至于旋转矩阵的应用,因子的顺序也应该颠倒,以便旋转是最后一个因素.经验法则是矩阵以从右到左的顺序应用,并且首先应用旋转(它是"MVP"的"M"部分),因此它需要是最右边的操作数.此外,您应该根据Ian Ni-Lewis的建议使用临时矩阵进行此计算(请参阅下面的更完整的答案):
float[] scratch = new float[16];
// Combine the rotation matrix with the projection and camera view
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
Run Code Online (Sandbox Code Playgroud)
感谢您提请注意这个问题.我会尽快修复培训课程和示例代码.
编辑:此问题现已在可下载的示例代码和OpenGL ES培训课程中得到纠正,包括对因子的正确顺序的评论.感谢您的反馈,伙计们!
Ian*_*wis 10
教程是不正确的,但许多错误要么相互抵消,要么在这个非常有限的环境中不明显(固定摄像机以(0,0)为中心,仅绕Z旋转).旋转是向后的,但否则它看起来是正确的.(要知道为什么这是错误的,请尝试一个不那么简单的相机:例如,设置眼睛并看看y = 1.)
使调试非常困难的一个原因是Matrix方法不对其输入进行任何别名检测.教程代码使您看起来可以使用与输入和结果相同的矩阵调用Matrix.multiplyMM.事实并非如此.但是因为实现每次都会增加一列,所以如果重新使用右侧(如当前代码,其中mMVPMatrix是rhs和结果),则重要的是,如果左侧重复使用,则不太明显. .在写入结果中的相应列之前,读取左侧的每列,因此即使覆盖LHS,输出也是正确的.但是如果右侧与结果相同,那么它的第一列将在完成读取之前被覆盖.
因此,教程代码处于一种局部最大值:看起来它是有效的,如果你改变了任何一件事,它就会突然爆发.这导致人们认为它看起来不对,它可能是正确的.;-)
无论如何,这里有一些替换代码,我认为是预期的结果.
Java代码:
@Override
public void onDrawFrame(GL10 unused) {
float[] scratch = new float[16];
// Draw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
// Draw square
mSquare.draw(mMVPMatrix);
// Create a rotation for the triangle
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, 1.0f);
// Combine the rotation matrix with the projection and camera view
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
// Draw triangle
mTriangle.draw(scratch);
}
Run Code Online (Sandbox Code Playgroud)
着色器代码:
gl_Position = uMVPMatrix * vPosition;
Run Code Online (Sandbox Code Playgroud)
注意:这些修正使投影正确,但它们也反转了旋转方向.那是因为原始代码以错误的顺序应用了转换.可以这样想:它不是顺时针旋转物体,而是逆时针旋转相机.当您修复操作顺序以便将旋转应用于对象而不是摄像机时,对象将开始逆时针运行.这不是矩阵错了; 它是用于创建矩阵的角度.
因此,要获得"正确"结果,您还需要翻转单元格的符号.
归档时间: |
|
查看次数: |
5634 次 |
最近记录: |