Kamujin's picture


Do you have any interest in adding a function to the Matrix4 structure to support creating an orthographic projection?

		public static Matrix4 CreateOrthographicProjection(float left, float right, float top, float bottom, float near, float far)
			float invRL = 1 / (right - left);
			float invTB = 1 / (top - bottom);
			float invFN = 1 / (far - near);
			float m11 = 2 * invRL;
			float m22 = 2 * invTB;
			float m33 = -2 * invFN;
			float m41 = - (right + left) * invRL;
			float m42 = - (top + bottom) * invTB;
			float m43 = - (far + near) * invFN;
			return new Matrix4
				new Vector4(m11,   0,   0,   0),
				new Vector4(  0, m22,   0,   0),
				new Vector4(  0,   0, m33,   0),
				new Vector4(m41, m42, m43,   1)			

Also, as I was studying the TextPrinter.PerformLayout function, I noticed that the comments look to be out of sync with the latest code.

            // Every character comprises of 4 vertices, forming two triangles. We generate an index array which
            // indexes vertices in a triangle-strip fashion. To create a single strip for the whole string, we
            // need to add a degenerate triangle (0 height) to connect the last vertex of the previous line with
            // the first vertex of the next line.

It looks like you are using triangle lists now and no longer use/need the degenerate triangle.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Thanks, I'll add the ortho function.

I'm going to spend this week cleaning up the text code. By the coming weekend, I hope this will be ready along with the DDS loaders.

Inertia's picture

Thanks, the function is correct according to http://www.glprogramming.com/red/appendixf.html

It might be good adding some Asserts to avoid division by 0, or put all float inv* = 1 / () into a try{} block?

the Fiddler's picture

It's a slight performance tradeoff, but I think the best course is to throw ArgumentExceptions when left == right etc.

Inertia's picture

Mhmm ok, Ortho calls will probably never become a bottleneck, but why do you dislike Debug.Assert( left != right && top != bottom && near != far, "The parameters passed to CreateOrthographicProjection will result in a division by zero." );

What I really like about the Debug class is that it won't be in release builds. Allows you to be as paranoid as you want when developing and debugging, without hurting performance in release builds (where this kind of error should never ever occur).

Kamujin's picture

I didn't put exception handling in because the Matrix4.Frustum() didn't include any.

I can see the logic of both approaches. As this function should never bottleneck, I think you can afford to use either mechanism.

kanato's picture

You should avoid doing Debug.Assert for this sort of thing in libraries. It's the C# compiler, not the JIT that eliminates these calls, so if someone is writing their application in debug mode, but they linked to the release version of the library, the Debug.Assert call will never get run and the error will be swallowed. My rule of thumb is that Assert should only be used if the bug it's checking for would be in the assembly it's in, but here if right == left then it's a problem with the calling code, not the library itself.

objarni's picture

As this function should never bottleneck, I think you can afford to use either mechanism.

Kamujin's picture

Very good point Kanato.

Inertia's picture

Indeed, this can happen. Not sure if that should be a concern to us, because if you follow the road of assuming the users to be unaware of what he's doing, you must check before every GL call if the context != null...

I'm cool with whatever way is chosen, it is just not pretty when a function aborts with a cryptic exception. We are past that "Guru meditation at 0x12345678" century ;)

kanato's picture

Yeah, checking the context every GL call would be overkill. But I think the usage scenario that I described is probably typical of how people will/do use OpenTK, because that's how most libraries are used. Usually you don't even get debug builds of libraries unless you compile them yourself, and even if they are there, Visual Studio won't automatically switch from debug to release versions of libraries based on the build configuration of your project (it only does this if both projects are part of the solution, and most people don't bother with downloading the source and adding the project files to their solutions).

Here especially, floating-point division by zero doesn't lead to an error, because float has representations for +/- infinity and NaN. So if the arguments lead to a divide by zero, the only thing you'll see is that nothing gets drawn on the screen at all, which is a pain to debug.