OpenGL move object and keep transformation
我有一个物体,它被转换了(在Y轴上旋转45度)。目标是在X轴和Y轴上移动(平移)对象,并保持变换效果不变。很难解释,所以我拍了张照片:
我知道OpenGL中相机的概念,我知道我不能真正移动相机,但事实上,所有东西都在相机周围移动。有人真的知道如何做到这一点吗?
我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //set mvp matrixProj = new PerspectiveProjectionMatrix(fovy, aspect, near, far); matrixView = new ModelMatrix(); matrixView.LookAtTarget(new Vertex3f(0, 0, 2), new Vertex3f(0, 0, 0), new Vertex3f(0, 1, 0)); matrixModel = new ModelMatrix(); matrixModel.SetIdentity(); matrixModel.RotateY(45); matrixModel.Translate(-2, -2, 0); Matrix4x4 mvp = matrixProj * matrixView * matrixModel; Gl.UniformMatrix4(Gl.GetUniformLocation(shaderProgram,"MVP"), 1, false, mvp.ToArray()); //draw quad Gl.Begin(PrimitiveType.Quads); Gl.Vertex3(-2, 2, 0); Gl.Vertex3(2, 2, 0); Gl.Vertex3(2, -2, 0); Gl.Vertex3(-2, -2, 0); Gl.End(); |
你必须改变指令的顺序。通过将对象的平移矩阵乘以旋转矩阵,围绕对象的轴执行旋转。这意味着您必须先进行平移,然后进行旋转。
1 2 3 4 | matrixModel = new ModelMatrix(); matrixModel.SetIdentity(); matrixModel.Translate(-2, -2, 0); matrixModel.RotateY(45); |
注意,翻译矩阵如下:
1 2 3 4 5 6 | Matrix4x4 translate; translate[0] : ( 1, 0, 0, 0 ) translate[1] : ( 0, 1, 0, 0 ) translate[2] : ( 0, 0, 1, 0 ) translate[3] : ( tx, ty, tz, 1 ) |
围绕y轴的旋转矩阵如下:
1 2 3 4 5 6 7 | Matrix4x4 rotate; float angle; rotate[0] : ( cos(angle), 0, sin(angle), 0 ) rotate[1] : ( 0, 1, 0, 0 ) rotate[2] : ( -sin(angle), 0, cos(angle), 0 ) rotate[3] : ( 0, 0, 0, 1 ) |
矩阵乘法的工作原理如下:
1 2 3 4 5 6 | Matrix4x4 A, B, C; // C = A * B for ( int k = 0; k < 4; ++ k ) for ( int l = 0; l < 4; ++ l ) C[k][l] = A[0][l] * B[k][0] + A[1][l] * B[k][1] + A[2][l] * B[k][2] + A[3][l] * B[k][3]; |
< BR>
1 2 3 4 | model[0] : ( cos(angle), 0, sin(angle), 0 ) model[1] : ( 0, 1, 0, 0 ) model[2] : ( -sin(angle), 0, cos(angle), 0 ) model[3] : ( tx, ty, tz, 1 ) |
< BR>注:
1 2 3 4 | model[0] : ( cos(angle), 0, sin(angle), 0 ) model[1] : ( 0, 1, 0, 0 ) model[2] : ( -sin(angle), 0, cos(angle), 0 ) model[3] : ( cos(angle)*tx - sin(angle)*tx, ty, sin(angle)*tz + cos(angle)*tz, 1 ) |
< BR>
答案的扩展:透视投影矩阵如下:
1 2 3 4 5 6 | r = right, l = left, b = bottom, t = top, n = near, f = far 2*n/(r-l) 0 0 0 0 2*n/(t-b) 0 0 (r+l)/(r-l) (t+b)/(t-b) -(f+n)/(f-n) -1 0 0 -2*f*n/(f-n) 0 |
在哪里?
1 2 3 4 5 | r = w / h ta = tan( fov_y / 2 ); 2*n / (r-l) = 1 / (ta*a) ---> 1/(r-l) = 1/(ta*a) * 1/(2*n) 2*n / (t-b) = 1 / ta ---> 1/(t-b) = 1/ta * 1/(2*n) |
如果要用偏移量(
1 2 3 4 5 6 7 | x_disp = 1/(ta*a) * x/(2*n) y_disp = 1/ta * y/(2*n) 1/(ta*a) 0 0 0 0 1/t 0 0 x_disp y_disp -(f+n)/(f-n) -1 0 0 - 2*f*n/(f-n) 0 |
设置透视投影矩阵如下:
1 2 3 4 5 6 | float x = ...; float y = ...; matrixProj = new PerspectiveProjectionMatrix(fovy, aspect, near, far); matrixProj[2][0] = x * matrixProj[0][0] / (2.0 * near); matrixProj[2][1] = y * matrixProj[1][1] / (2.0 * near); |
对于
1 2 3 4 5 6 | float x_pixel = .....; float y_pixel = .....; float x_dipl = (right - left) * x_pixel / width_pixel; float y_dipl = (top - bottom) * y_pixel / height_pixel; glFrustum( left + x_dipl, right + x_dipl, top + y_dipl, bottom + y_dipl, near, far); |