luca-piccioni / OpenGL.Net

Modern OpenGL bindings for C#.
MIT License
570 stars 109 forks source link

Matrix multiplication #34

Closed ghost closed 7 years ago

ghost commented 7 years ago

Dear Luca,

Hi again. While trying to do unprojection, I started playing with matrices and came upon the following effect: multiplying a Matrix4x4f with a Matrix1x4f resulted in a Matrix4x4f, rather than in a Matrix1x4f. After installing MathNet.Numerics and using their matrices I was able to unproject successfully.

Also, I compared the results of the multiplication of the projection and modelview 4x4 matrices using the matrices from OpenGL.Net and using MathNet.Numerics.LinearAlgebra. The products contained different numbers, although the source matrices contained the same numbers in the buffers.

Best, Daniel

luca-piccioni commented 7 years ago

OpenGl.Net does not defines a Matrix1x4f class. Showing the code would be of a great help. Typically I use Matrix4x4 with a Vertex4f.

Notice that I use GLSL operand order, so it may be different from other matrix libraries. Moreover che ck whether Math.Ne5 uses row-majoe or column-major order.

ghost commented 7 years ago

I will create a small demo project in the evening and attach it here.

ghost commented 7 years ago

Hi Luca,

Here is the demo project. Take a look at the console.

Incident one demonstrates that the multiplication of the modelview and the projection matrices produces different results when done with the OpenGL.NET Matrix and the MathNet Matric, and the difference cannot be explained by sheer rounding. I cannot say which result is the correct one.

Incident two demonstrates that multiplying a 4x4 matrix with a 1x4 vector produces a 4x4 matrix, while it should produce a 1x4 vector. Actually, now, after testing with MathNet I can see that the first column of the resulting 4x4 matrix is the vector we are looking for, but it is not obvious, and, anyway, it's mathematically incorrect.

MatrixTest.zip

Best, Daniel

luca-piccioni commented 7 years ago

Indeed you executed a non-working-because-never-used code. Thank you!

I've never used Matrixclass, since the most cases are resolved using Matrix4x4, Matrix3x3and ModelMatrix: they have specialized operators that unroll required loops. I suggest you to use the above classes. For vertices, uses Vertex* structures (wiki).

ghost commented 7 years ago

Glad I can help :) And thank you for the explanation!

I noticed another peculiarity, but I'm not sure whether it is a problem. I experimented with two different ways to setup perspective projection:

1.

//https://gist.github.com/sixman9/871099 Gl.MatrixMode(MatrixMode.Projection); Gl.LoadIdentity(); float aspect = (float)this.size.Height / (float)this.size.Width; float fieldOfView = 45; float zNear = 0.01f; float zFar = 1000.0f; float fH = (float)Math.Tan(fieldOfView 3.14159f / 360.0f) zNear; float fW = fH * aspect; Gl.Frustum(-fW, fW, -fH, fH, zNear, zFar);

2.

Gl.MatrixMode(MatrixMode.Projection); float aspect = (float)this.size.Height / (float)this.size.Width; float fieldOfView = 45; float zNear = 0.01f; float zFar = 1000.0f; PerspectiveProjectionMatrix pjmatrix = new PerspectiveProjectionMatrix(fieldOfView, aspect, zNear, zFar); Gl.LoadMatrix(pjmatrix.ToArray());

What I noticed is that both methods create perspective, but the results are very different. Unfortunately, I have no prior experience with 3D graphics and I have no idea what exactly's going on.

luca-piccioni commented 7 years ago

I think you are calling the wrong glFrustum. Try change the Gl.Frustum to

Gl.Frustum((double)-fW, (double)fW, (double)-fH, (double)fH, (double)zNear, (double)zFar);

I think you are facing the same problem you got using Gl.Ortho.