I've a object, which is transfomred (rotated at 45deg on the Y axis).
The target is to move (translate) the object on the x and y axis and keep the transformation effect as it is.
Its very hard to explain, so I made a picture:
I know the concept of the camera in opengl and i know i cant really move the camera but in fact everything is moving around the camera. Does someone actually know how to achieve this?
My code:
//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();
You have to change the order of the instructions. A rotation around the axis of the object is performed, by multiplying the translation matrix of the object by the rotation matrix. This means you have to do the translation first and then the rotation.
matrixModel = new ModelMatrix();
matrixModel.SetIdentity();
matrixModel.Translate(-2, -2, 0);
matrixModel.RotateY(45);
Note, the translation matrix looks like this:
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 )
And the rotation matrix around Y-Axis looks like this:
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 )
A matrix multiplication works like this:
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];
The result of translate * rotate
is this:
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 )
Note, the result of rotate * translate
would be:
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 )
A perspective projection matrix looks like this:
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
where :
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)
If you want to displace the filed of view by an offset (x
, y
), then you have to do it like this:
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
Set up the perspective projection matrix like this:
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);
To glFrustum
, a pixel offset, can be applied like this:
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);