digitalmars.D.learn - Problem with gfm.math.matrix (some gamedevs out there ?)
- Thomas (44/44) Sep 03 2020 Hi!
- drug (10/69) Sep 03 2020 1. zNear should not be equal to zero, this makes your matrix singular
- Mike Parker (27/58) Sep 03 2020 This is not the problem, but FYI these two lines are reduntant:
- Thomas (2/73) Sep 03 2020 Thank you very much! Both of you!
- Guillaume Piolat (4/15) Sep 04 2020 As others said, zNear is zero so your matrix is not invertible.
Hi! I am following some examples in C++ about how OpenGL is working. There are great tutorials out there and most of it works also with D. For my code I am using gfm.math.matrix (Version 8.0.3) to be able to calculate the mouse position in a 3d world. Now I have some problems with the projection matrix by inverting it. My example code: --------------------- import std.stdio; int main() { import gfm.math.matrix; const int width = 800; const int height = 600; auto projectionMatrix = mat4!(float).identity(); auto ratio = cast(float)width / cast(float)height; projectionMatrix = mat4!(float).perspective( 45.0f, ratio, 0.0f, 100.0f ); writeln("projectionMatrix: ", projectionMatrix ); auto inversedMatrix = mat4!(float).identity(); inversedMatrix = projectionMatrix.inverse(); // <-- why this does not work ? writeln("inversedMatrix: ", inversedMatrix ); return 0; } The projection matrix will be calculated correctly with [1.34444, 0, 0, 0, 0, 1.79259, 0, 0, 0, 0, -1, -0, 0, 0, -1, 0] assuming that the screen size is 800x600. But using the .inverse() function in gfm returns only a matrix with following values: [-nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, inf, -inf] I don't know what I am doing wrong here: - do I call the function wrong way ? (but there is no other way) - is there a bug in the function ? (I do not believe that because the library is battle proved) So I looked a couple of hours for an answer, but did not find anything useful. Is somebody out there who could help me out ? Maybe one developer of the d gfm library ? Thank you for you time! Thomas
Sep 03 2020
On 9/3/20 3:36 PM, Thomas wrote:Hi! I am following some examples in C++ about how OpenGL is working. There are great tutorials out there and most of it works also with D. For my code I am using gfm.math.matrix (Version 8.0.3) to be able to calculate the mouse position in a 3d world. Now I have some problems with the projection matrix by inverting it. My example code: --------------------- import std.stdio; int main() { import gfm.math.matrix; const int width = 800; const int height = 600; auto projectionMatrix = mat4!(float).identity(); auto ratio = cast(float)width / cast(float)height; projectionMatrix = mat4!(float).perspective( 45.0f, ratio, 0.0f, 100.0f ); writeln("projectionMatrix: ", projectionMatrix ); auto inversedMatrix = mat4!(float).identity(); inversedMatrix = projectionMatrix.inverse(); // <-- why this does not work ? writeln("inversedMatrix: ", inversedMatrix ); return 0; } The projection matrix will be calculated correctly with [1.34444, 0, 0, 0, 0, 1.79259, 0, 0, 0, 0, -1, -0, 0, 0, -1, 0] assuming that the screen size is 800x600. But using the .inverse() function in gfm returns only a matrix with following values: [-nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, inf, -inf] I don't know what I am doing wrong here: - do I call the function wrong way ? (but there is no other way) - is there a bug in the function ? (I do not believe that because the library is battle proved) So I looked a couple of hours for an answer, but did not find anything useful. Is somebody out there who could help me out ? Maybe one developer of the d gfm library ? Thank you for you time! Thomas1. zNear should not be equal to zero, this makes your matrix singular and inversion of singular matix is impossible so you get nans and infs. Make zNear a little bit more than zero and your code will work 2. FOV in perspective should be expressed in radians, not degrees so this fixes your problem: ``` projectionMatrix = mat4!(float).perspective( 45.0f * 3.14 / 180., ratio, 0.01f, 100.0f ); ```
Sep 03 2020
On Thursday, 3 September 2020 at 12:36:35 UTC, Thomas wrote:My example code: --------------------- import std.stdio; int main() { import gfm.math.matrix; const int width = 800; const int height = 600; auto projectionMatrix = mat4!(float).identity(); auto ratio = cast(float)width / cast(float)height; projectionMatrix = mat4!(float).perspective( 45.0f, ratio, 0.0f, 100.0f ); writeln("projectionMatrix: ", projectionMatrix ); auto inversedMatrix = mat4!(float).identity(); inversedMatrix = projectionMatrix.inverse(); // <-- why this does not work ? writeln("inversedMatrix: ", inversedMatrix ); return 0; }This is not the problem, but FYI these two lines are reduntant: auto projectionMatrix = mat4!(float).identity(); auto inversedMatrix = mat4!(float).identity(); This is all you need: auto projectionMatrix = mat4!(float).perspective( 45.0f, ratio, 0.0f, 100.0f ); auto inversedMatrix = projectionMatrix.inverse(); `perspective` and `inverse` return new instances that overwrite the two identity matrices you initialized, so you're doing work you don't need to do.The projection matrix will be calculated correctly with [1.34444, 0, 0, 0, 0, 1.79259, 0, 0, 0, 0, -1, -0, 0, 0, -1, 0] assuming that the screen size is 800x600. But using the .inverse() function in gfm returns only a matrix with following values: [-nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, inf, -inf] I don't know what I am doing wrong here: - do I call the function wrong way ? (but there is no other way) - is there a bug in the function ? (I do not believe that because the library is battle proved)My guess is the problem is in the `inverse` implementation: https://github.com/d-gamedev-team/gfm/blob/master/math/gfm/math/matrix.d#L448 T invDet = 1 / det; It doesn't check if det is 0. This shows 1f / 0f results in `inf`: import std; void main() { float f = 0; float i = 1 / f; writeln(i); } https://run.dlang.io/is/ZyggRg With all those zeroes in the perspective matrix and all the multiplications in the `inverse` function, I guess things are getting wonky.
Sep 03 2020
On Thursday, 3 September 2020 at 13:31:01 UTC, Mike Parker wrote:On Thursday, 3 September 2020 at 12:36:35 UTC, Thomas wrote:Thank you very much! Both of you!My example code: --------------------- import std.stdio; int main() { import gfm.math.matrix; const int width = 800; const int height = 600; auto projectionMatrix = mat4!(float).identity(); auto ratio = cast(float)width / cast(float)height; projectionMatrix = mat4!(float).perspective( 45.0f, ratio, 0.0f, 100.0f ); writeln("projectionMatrix: ", projectionMatrix ); auto inversedMatrix = mat4!(float).identity(); inversedMatrix = projectionMatrix.inverse(); // <-- why this does not work ? writeln("inversedMatrix: ", inversedMatrix ); return 0; }This is not the problem, but FYI these two lines are reduntant: auto projectionMatrix = mat4!(float).identity(); auto inversedMatrix = mat4!(float).identity(); This is all you need: auto projectionMatrix = mat4!(float).perspective( 45.0f, ratio, 0.0f, 100.0f ); auto inversedMatrix = projectionMatrix.inverse(); `perspective` and `inverse` return new instances that overwrite the two identity matrices you initialized, so you're doing work you don't need to do.The projection matrix will be calculated correctly with [1.34444, 0, 0, 0, 0, 1.79259, 0, 0, 0, 0, -1, -0, 0, 0, -1, 0] assuming that the screen size is 800x600. But using the .inverse() function in gfm returns only a matrix with following values: [-nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, -nan, inf, -inf] I don't know what I am doing wrong here: - do I call the function wrong way ? (but there is no other way) - is there a bug in the function ? (I do not believe that because the library is battle proved)My guess is the problem is in the `inverse` implementation: https://github.com/d-gamedev-team/gfm/blob/master/math/gfm/math/matrix.d#L448 T invDet = 1 / det; It doesn't check if det is 0. This shows 1f / 0f results in `inf`: import std; void main() { float f = 0; float i = 1 / f; writeln(i); } https://run.dlang.io/is/ZyggRg With all those zeroes in the perspective matrix and all the multiplications in the `inverse` function, I guess things are getting wonky.
Sep 03 2020
On Thursday, 3 September 2020 at 12:36:35 UTC, Thomas wrote:--------------------- import std.stdio; int main() { import gfm.math.matrix; const int width = 800; const int height = 600; auto projectionMatrix = mat4!(float).identity();Note that instead of `mat4!(float)` you can just use `mat4f`.auto ratio = cast(float)width / cast(float)height; projectionMatrix = mat4!(float).perspective( 45.0f, ratio, 0.0f, 100.0f );As others said, zNear is zero so your matrix is not invertible. I guess perspective should warn about that.
Sep 04 2020