GL.LoadMatrix(Matrix4) overload..?

I wanted to use the LoadMatrix method of the GL class.. found lots of overloads, but none of them taking a Matrix4 (or ref to it ..) as an argument.

Is this a known issue or should I put up an item about it somewhere..? (where?)

Overall I'm so far very pleased with my OpenTK experience.. Keep up the good work!


Comments

You can use the ref/out
posted by Inertia

You can use the ref/out overloads for this task. Remember that OpenTK.Math matrices are row-major, OpenGL itself expects a column-major matrix when using GL.LoadMatrix and will convert into this convention internally.

Either use this:

GL.MatrixMode( MatrixMode.Modelview );
GL.LoadTransposeMatrix( ref m1.Row0.X );
// proof
GL.GetFloat( GetPName.ModelviewMatrix, out m2.Row0.X );
m2.Transpose( );

...or manually m1.Transpose (if this is the end of the Matrix4's lifespan) before calling GL.LoadMatrix instead of using GL.LoadTransposedMatrix.

You got my support for your request for a Matrix4 overload, but I start to get afraid that Fiddler will ban me (or worse: send a horde of hamsters to assassinate me), if I keep making Wishlists ;)
Something that would be very nice too are GL.GetFloatVector2/3/4 and GL.GetFloatMatrix4 functions added to GL. I cannot currently recall what query would return a Vector2, but there's probably some (window size? texcoords?)

...pleased with my OpenTK experience
Regarding the fun using OpenTK, I can only agree.

Thanks for your support
posted by objarni

Thanks for your support Inertia!

For me, using 'ref float' and 'float*' when calling a method means different things. 'ref float' means sending a reference to a single float variable. In this case, that would mean the very first element of the first row, ie. element 0,0 of the matrix.

So, internally, GL.LoadTransposeMatrix must make some guesses about the layout of memory after that 'variable' then?

This behaviour seems not-so-C#-ish if you know what I mean.. Is there something I'm missing here?

I would really prefer sending 'ref Matrix4' or 'float*', in that order of preference. (or even better, simply Matrix4, ie. letting the matrices be of class type.. but I know I've got the performance-politics against me here! ;)

I guess this might be showing up in the next OpenTK release?

The only difference between
posted by the Fiddler.

The only difference between 'float*' and 'ref float' is that the pointer is passed directly to the unmanaged function in the first case, while the object is first pinned before passing a pointer in the second version. Apart from this, they behave identically - in this case 'ref float' effectively is a managed version of a pointer.

This is actually defined in the C# specs (I didn't believe that either until someone posted a link to the actual paragraph), and is very useful in the case when you want to pass an array starting from the nth element. The only requisite for this is to define the class/struct with LayoutKind.Sequenctial attribute (IIRC, structs have this by default).

I'd like to add Matrix/Vector overloads wherever it makes sense, but I'm pressed for time (getting internet explorer to work with the new theme is taking way too much time). Even a simple list of missing overloads would help a lot.

@objarni You're welcome, and
posted by Inertia

@objarni
You're welcome, and yes: internally OpenGL uses column major matrices no matter if you used GL.LoadTransposeMatrix or manually transpose first, it's only about the order of the 16 float in memory. Knowing the difference and as long as you remember that querying the matrix will give you something column-major you should be fine :)
I don't think you are missing anything there, IMHO you should not be too worried about performance implications due to the matrix being transposed.

@Fiddler
The uses for Matrix4 I can come up with:
GL.LoadMatrix
GL.LoadTransposeMatrix
GL.MultMatrix
GL.GetFloat( Modelview/Projection/Texture Matrix
GL.UniformMatrix4* (this one accepts Matrix[] too, but I don't understand why there are so many permutations?)
Edit: Quote from orangebook on glUniformMatrix: "The number in the command name is interpreted as the dimensionality of the matrix. The number 2 indicates a 2 x 2 matrix (i.e., 4 values), the number 3 indicates a 3 x 3 matrix (i.e., 9 values), and the number 4 indicates a 4 x 4 matrix (i.e., 16 values)."

Thanks for your answers,
posted by objarni

Thanks for your answers, this clears things up.

Just out of curiosity: why wasn't the Matrix4 layout choosen to be the same as OpenGL's? It seems they are quite 'close' anyway (OpenTK relies on OpenGL) so that would be the "naive" choice.

(going back to my Casual 3d game in C#-project)

Hmm. I saw the news about
posted by objarni

Hmm. I saw the news about errors in the Matrix4 implementation, regarding both RotateX, Mult and Rotate, all three of which I'm using in my game to no success. I guess I'll have to wait with that part of the game until OpenTK-0.3.14 is out!

I've asked the same thing,
posted by Inertia

I've asked the same thing, and I remember the answer to be that row-major matrices allow some CPU optimizations. Using row-major matrices seems to be so common (DirectX uses row-major too) that most OpenGL functions accepting matrices also have a parameter to specify if the matrix should be transposed by GL when incoming to the function. My guess is that this has been requested by developers who write both, a DX renderer and a GL renderer. One matrix layout to rule them all ;)

If you don't want to wait for the update, you can still use GL.Rotate or GL.MultMatrix to calculate the orientations.

You made me curious though, a Casual 3d game? :)

OK I'll just swallow that
posted by objarni

OK I'll just swallow that (why is it always performance that makes things complicated/ugly looking? Can't performance and elegance go hand-in-hand every once in a while..)

Thanks for the tips. I'll rewrite my "rendering interface" from using Matrix4 to using specific operations like rotate etc. so I will be able to use the ordinary GL.Rotate/Translate methods "under the hood" and skip Matrix4 altogether.

Yeah I'm doing a simple, non-original casual 3d game using OpenTK, nothing playable yet just a model viewer, but you can see a low-resolution in-game concept art image here:

http://sourceforge.net/projects/dogfight2008/

Basically it's a remake of an old classic Amiga game I loved back in the days, called "Dogfight" simply, with two instead of four human players (don't you just hate PC-keyboards..? Pressing more than two keys simultaneously is just worthless..)

Indeed, optimized code is
posted by Inertia

Indeed, optimized code is often hard to follow if you didn't write it yourself (one of the main reasons why I never liked C(++) much).
It might be just me, but I do like the ref/out stuff in OpenTK. It has the advantage that the code is very clear about if you are passing by value or reference (which can lead to very hard-to-trace bugs if you're not careful) and it's not much more typing to do. But then I'm also one of those people who explicitly declare private members, give enums an explicit type and declare struct-layout/attribs wherever I can, no matter if it's default or not. I just believe it leads to more expressive code, which is worth the little extra typing.

Good choice regarding the game :) This is the kind of game one person can accomplish in a reasonable timeframe, I hereby thank god that Tao/OpenTK users are more sane than XNA users (half the people using XNA are (trying to) developing MMORPGs or 3D Shooters) ;)
I've had an [brag]Amiga 500 with 1MB Ram[/brag], but have to admit I've never heard of Dogfight. The image looks like it's plane vs. plane dogfight, each starting at their own tower and battling it out in the air?

Regarding multiple keystrokes, it is already quite tight when 2 players are using the same keyboard. If you play the game more than 5 minutes, it will start getting uncomfortable too. I think you should rather consider gamepads/joysticks or maybe even the mouse as control devices, rather than trying to force 4 players to use the same keyboard.

P.S. You are using VS2005, is there any reason why you're avoiding 2008?

Indeed, optimized code is
posted by objarni

Indeed, optimized code is often hard to follow if you didn't write it yourself (one of the main reasons why I never liked C(++) much).
It might be just me, but I do like the ref/out stuff in OpenTK. It has the advantage that the code is very clear about if you are passing by value or reference (which can lead to very hard-to-trace bugs if you're not careful) and it's not much more typing to do. But then I'm also one of those people who explicitly declare private members, give enums an explicit type and declare struct-layout/attribs wherever I can, no matter if it's default or not. I just believe it leads to more expressive code, which is worth the little extra typing.

Yeah I agree about being explicit. But I am (nowadays) used to thinking "reference" when I am passing "an object" to a method in C#. I think I got into this thinking when I made a (quick) dive into java a couple of years ago, some applet-game-hack I put together. In java every object is passed by reference, never by value. So to me having a method taking a Matrix4 simple tells me it is passed by reference. I guess you can see why I dislike 'ref' -- it is already passed by reference to me! This is also one of the reasons I prefer immutable objects instead of mutable objects -- it reduces the hard-to-trace bugs you too are referring to. That kind of bugs are also known as aliasing bugs, IIRC.

Good choice regarding the game :) This is the kind of game one person can accomplish in a reasonable timeframe, I hereby thank god that Tao/OpenTK users are more sane than XNA users (half the people using XNA are (trying to) developing MMORPGs or 3D Shooters) ;)
I've had an [brag]Amiga 500 with 1MB Ram[/brag], but have to admit I've never heard of Dogfight. The image looks like it's plane vs. plane dogfight, each starting at their own tower and battling it out in the air?

Thanks! The planes are supposed to start at ground level. The towers are simply part of the background imagery. Dogfight for the Amiga was just a really small public domain game. It was nothing fancy, but it was so darn fun to play. I guess there are numerous remakes already, but I haven't seen one for OpenTK/quasi 3d yet :)

Regarding multiple keystrokes, it is already quite tight when 2 players are using the same keyboard. If you play the game more than 5 minutes, it will start getting uncomfortable too. I think you should rather consider gamepads/joysticks or maybe even the mouse as control devices, rather than trying to force 4 players to use the same keyboard.
Yeah thats why I plan keeping it at two players, and using as few keys as possible, namely three per player. Since you usually don't try to fly up and down at the same time, the usual amount of keys pushed is 0-2, with single additional strokes every now and then to fire a shot. So at most 4 keys simultaneously. I hope to use "safe keys" for the firing -- shift and such. Have to experiment a little.

I'm using Visual2005 because that's what I'm used to. And I'm targeting .NET2.0/mono1.2.6, so I see no real benefit of using VS2008 for this project. (though I like the new lambda-stuff they put into C#3.. but not enough to go through the hassle of upgrading this project to it..)

I guess you can see why I
posted by Inertia

I guess you can see why I dislike 'ref' -- it is already passed by reference to me!
For classes that is true anyway, if it really bothers you with structs you could wrap them into classes. Maybe that's just what you need? You could assign only get {} properties to make it immutable, so the constructor is the only way to change any members.

[Dogfight]
Indeed, the old Amiga games had usually very good controls and much more focus on gameplay mechanics than graphics. My first game for XNA was a remake of a classic too, those kind of games are achievable and a rather good motivation.

[VS2005]
Upgrading projects from 2005 to 2008 is uncomplicated (wizard helps). Just asking because I'm occasionally having trouble using the online-help (it will just show "topic not found").

For classes that is true
posted by objarni

For classes that is true anyway, if it really bothers you with structs you could wrap them into classes. Maybe that's just what you need? You could assign only get {} properties to make it immutable, so the constructor is the only way to change any members.
Wrapping a basic API-level type as Matrix4 into an immutable class, say Matrix4c where 'c' stands for 'constant', is one possibility. But writing expressions using that type soon become cumbersome, unless I overload all operations used. Not elegant and error-prone too. But of course, once it's done it's done; matrices and their operations have been the same for the last couple of hundred years I hazard :). Maybe I'll consider this once OpenTK0.3.14 is out with a corrected Matrix4 implementation. Thanks!

But anyway right now I've followed your previous advice and I'm staying with GL.Translate/Rotate instead of sending the transform matrix in the method MeshAt (which I've renamed to DrawMesh simply), and this is working out great. It is also more natural since I'm used to this method.

Now onto Text rendering!

Indeed that's one of the
posted by Inertia

Indeed that's one of the great things about OOP, it allows constructs that are much closer to human ways of thinking. Sure you will have to write quite some overloads to get this working, but if using structs really bothers you that much it *can* be done :)

btw. did you see the OpenGL Articles in the Documentation? http://opentk.sourceforge.net/home/?q=node/141
I think Fiddler is in jail and only has 5 mins inet per day or so ;-) I could really use some feedback if they are on the right track or totally off? One issue is: things are rather simple using C# and OpenTK, I don't really know what else to cover in most topics, without artificially stretching the pages by quoting or adding pictures?

btw. did you see the OpenGL
posted by objarni

btw. did you see the OpenGL Articles in the Documentation? http://opentk.sourceforge.net/home/?q=node/141
I think Fiddler is in jail or so

Yeah where is the Fiddler :) I'm really eager for the new OpenTK version to be downloadable hehe

and I could really use some feedback if they are on the right track or totally off? One issue is: things are rather simple using C# and OpenTK, I don't really know what else to cover in most topics, without artificially stretching the pages by quoting or adding pictures?

Well I liked the fast-read through I did now, especially that about VBO's (http://opentk.sourceforge.net/home/?q=node/144). But I guess that is because I've wondered how VBO's are used/thought of by someone with the knowledge. For Dogfight I'll go with good-old Display Lists though, but for future enterprises it might be nice.

In general, I think the documentation of OpenTK should be about "the glue" inbetween GL/AL and C#. That is: how do you use the classes, how should you think while developing a GLControl application / GameWindow application, more than how to draw OpenGL primitives. There are TONS of documentation about GL out on the net, and replicating that information is just a waste of resources. If OpenTK is close enough to the C API OpenGL, all that is needed is a way of mentally translating C-API info about GL into OpenTK's lingua, if you know what I mean. For example:

http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/...

That is quite easy for me to translate into OpenTK lingua, since I know all gl* method are in the GL class:

GL.DepthMask(true);

I really don't need this translated into exact OpenTK lingua, and as a high-level user of OpenTK (programming games using OpenTK) I can't see anything wrong with OpenTK's documentation lacking that piece.

What would be really nice would be lots of examples of specific techniques to be well documented, for example the last few days I've been spending lots of time searching/traversing files in order to get the following (rather simple) things to work alright in OpenTK:

* How to render Hello World on a Windows.Forms/GLControl
* How to render Hello World on a GameWindow
* How to achieve frame rate independent animation (measuring time) in a Windows.Forms/GLControl application
* How to achieve frame rate independent animation (measuring time) in a GameWindow application

That kind of pragmatic and hard-to-find information is really useful as OpenTK documentation. And not just examples! The examples are good for demonstrating what is possible / benchmarking / testing purposes on different platforms, but they are not optimal when it comes to readability / documentation! I remeber once I downloaded DirectX SDK and saw their samples/examples. They were more like demos, they were usually *very hard* to read, at least in my opinion.

Of course, all this is my 2 cents only :)

Thank you, that's what I
posted by Inertia

Thank you, that's what I assumed too. Articles explicitly demonstrating use of Techniques is probably what 80% of the Documentation will be like. I didn't see how to avoid the topics Vertex and Primitive Type, this is essential to know for beginners.

replicating that information is just a waste of resources
Indeed, but still there must be some kind of documentation showing the differences to the C API. Since the OpenGL bindings come from a generator there's no .

P.S. Sorry if replies are slow, retouching the Articles in the book.

objarni: ...the
posted by Inertia

objarni: ...the performance-politics against me here
I'm afraid this is inevitable, because when people hear "managed code" they usually start arguing that C(++) assembler is much faster. This was (is?) also a main topic for XNA, I really wish I could find the video again they made about unmanaged vs. managed code.

In that video one programmer from Garage Games showed a port of their game Marble Blast running in XNA. He said that the managed C# XNA version has 98% of the performance of the unmanaged C++ DX version, which was used to port. These 98% were achieved with a straight port, as in no XNA specific optimizations.

If you think you have better luck googling for it, I'm rather sure the video was made 2006 at a Microsoft conference (Gamefest?).

Correction: I've missed a
posted by Inertia

Correction:
I've missed a function that could use a Matrix4 overload

GL.MultTransposedMatrix()

also what I said about GL.Get* the Matrix from GL is not the only option. You can get the transposed Matrix directly from GL, see link

http://www.opentk.net/node/172

I've been working on Vector,
posted by JTalton

I've been working on Vector, Matrix, and Quaternion structs. I wrote a test program and made sure that the Matrix code was completely compatible with OpenGL. I personally need double precision so I have implemented both single and double point precision. I tested the performance of implementing them as immutable classes vs structs and structs were a lot faster. Immutable does not really give you much when you are working with structs since any time you pass one it creates a copy (unless by ref). I then did performance testing on passing by value vs by ref of structs, and of course the pass by ref was much faster. I also tested operator overloads vs function calls and function calls were MUCH faster since things could be passed by ref and not copied.

While not the most elegant, it is as fast as I can make it.

Since this is an example of
posted by objarni

Since this is an example of an as-ugly-as-it-gets situation, I think it is the most interesting comparison performancewise:

1) pass-by-ref structs in methods eg.
Vector3.Add(ref v1, ref v2, out result)

2) operator overloaded classes eg.
Vector3 result = v1 + v2;

How many percent slower was 2) compared to 1) ?

Timing Tests  202 :
posted by JTalton

Timing Tests
 202 : a.Add(ref b);
 236 : Vector4D.Add(ref a, ref b, out c);
 252 : a.Add(b)
1110 : c = Vector4D.Add(ref a, ref b);
1172 : c = a + b;

So by my tests, it is over 4 times as fast, which is significant enough to justify UGLY,
and I do agree that the pass-by-ref structs is a ton uglier then an overload.

I think the performance is related to the size of the struct since much of it caused by the copies.
I performed the same test with Vector4F which is half the size and had much of the same results.

Vector4D Add Functions
    public void Add(ref Vector4D vector);
    public void Add(ref Vector4D vector, out Vector4D result);
    public static void Add(ref Vector4D left, ref Vector4D right, out Vector4D result);

I also have an implementation of Vector4d that is an immutable class,
and it's performance is MUCH worse than the struct implementation.

Thanks! Do you have any idea
posted by objarni

Thanks!

Do you have any idea why immutability makes is even worse? I see no apparent reason why 'Vector2 Add(Vector2,Vector2)' should be any slower if the Vector2 is immutable..? (Compared with 'void Add(Vector2)' the reason is clear! No new vector, just update 'this' members!)

Thank you JTalton! I'm sure
posted by Inertia

Thank you JTalton!

I'm sure there's alot of users who will favor double over single precision, and tbh I find "a.Add(ref b);" pretty attractive ;)

Maybe start a new topic for discussing the VectorXd structs, it will go under inside this topic.

The question is - what does
posted by JTalton

The question is - what does making a struct immutable give you?

Immutable classes make a lot of sense where you can share an object by many other objects and not have to worry that the object will change. This is why the .NET strings are implemented this way. It allows strings to be referenced from many different places without fear of the string being modified. Only the reference is passed when making function calls etc. Setting a = b changes what a is referencing.

Immutable structs can never really be immutable. Every variable of the struct is it's own copy. Modifying it will only modify that copy. Setting a = b copies the contents of b into a.

If Vector was immutable:
It is true that in Vector Add( Vector a, Vector b) you cannot modify a or b in the function. This function makes a copy of each of the input parameters and a copy for the output parameter. That ends up being expensive.

Calling by ref passes a reference to the struct with is a lot faster than having a copy made.

Basically it comes down to the fact that since structs are value types (i.e. their own copy) they really can't be made immutable.

[Immutability] I agree that
posted by objarni

[Immutability]
I agree that the general approach today is to use modifiable (mutable) structs for Vectors, Quaternions and Matrices, for performance reasons. I believe I am not the only one who views the syntax as not the most elegant available in C#.

My question is simply academic: why would the performance of the operation

static VectorN Add(ref VectorN, ref VectorN)

.. depend on whether the struct VectorN is immutable or not? Since it has to allocate a new VectorN and do N additions. No VectorN member is modified at all.

Do you have the benchmarks for the operations available, eg. for Matrix4? It would be interesting to know how this "scales up" to structs with more members (comparing ref'ed structs to classes especially).

I do not think the
posted by JTalton

I do not think the performance of static VectorN Add(ref VectorN, ref VectorN) would be any different with immutable vs non-immutable structures.

My testing shows that static void Add(ref VectorN, ref VectorN, out VectorN) is a much faster function, and since it is using out, you need to be able to modify the out VectorN.

static VectorN Add(ref VectorN, ref VectorN) probably pushes the result from the function onto the stack and then has to do a copy to the variable that is being assigned in the operation. ( i.e. c = Add(a, b) ) That would explain the performance being 4 times as long.

Time | Function
-----------------------------------------
 236 : Vector4D.Add(ref a, ref b, out c);
1110 : c = Vector4D.Add(ref a, ref b);

The other problem with using immutable structs and static VectorN Add(ref VectorN, ref VectorN) is that since the parameters are passed as ref, in the function someone could call a = b, which even if the struct is immutable will still overwrite the fields in the struct essentially modifying the source Vector that was passed into the function. Thus the struct really is not immutable. Removing the ref adds even more overhead and slows the function down.

Immutable Classes
With immutable classes you have to allocate a new class to return, since you cannot modify the class. This call into the .NET memory manager usually will increase the execution time by double vs structs which are put on the stack. When I tested the Vector as a class, my timing numbers went up a good bit.

Looking on the net, I found a web page with the following numbers when they were testing the same thing:

Struct:            0.05
Immutable Struct:  0.10
Immutable Class:   0.25

The mutable struct is the fastest since they modify its data directly.

I do not have any performance tests setup for the matrix code.

I do whole heartedly agree that Add( ref a, ref b, out c ) is a ton uglier than c = Add( ref a, ref b ) which is uglier than c = Add( a, b ) which is uglier than c = a + b but it is MUCH faster.