Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
September 03, 2020 Problem with gfm.math.matrix (some gamedevs out there ?) | ||||
---|---|---|---|---|
| ||||
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 |
September 03, 2020 Re: Problem with gfm.math.matrix (some gamedevs out there ?) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas | 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!
>
> Thomas
1. 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 );
```
|
September 03, 2020 Re: Problem with gfm.math.matrix (some gamedevs out there ?) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas | 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. |
September 03, 2020 Re: Problem with gfm.math.matrix (some gamedevs out there ?) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | 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:
>
>>
>> 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.
Thank you very much! Both of you!
|
September 04, 2020 Re: Problem with gfm.math.matrix (some gamedevs out there ?) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas | 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. |
Copyright © 1999-2021 by the D Language Foundation