我有一个物体,它是变形的(在Y轴上以45度旋转)。
目标是在x和y轴上移动(平移)对象并保持转换效果。
很难解释,所以我拍了一张照片:
我知道opengl中相机的概念,我知道我不能真正移动相机,但实际上一切都在相机周围移动。有人真的知道如何实现这个目标吗?
我的代码:
//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();
答案 0 :(得分:3)
您必须更改说明的顺序。通过将对象的平移矩阵乘以旋转矩阵,执行围绕对象的轴的旋转。 这意味着您必须先进行平移,然后进行旋转。
matrixModel = new ModelMatrix();
matrixModel.SetIdentity();
matrixModel.Translate(-2, -2, 0);
matrixModel.RotateY(45);
注意,翻译矩阵如下所示:
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轴的旋转矩阵如下所示:
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 )
矩阵乘法的工作原理如下:
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];
translate * rotate
的结果是:
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 )
请注意,rotate * translate
的结果为:
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 )
透视投影矩阵如下所示:
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
其中:
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)
如果您想通过偏移(x
,y
)取代视野,那么您必须这样做:
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
设置透视投影矩阵,如下所示:
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);
要glFrustum
,像素偏移量可以像这样应用:
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);