Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Graphics Data Structures with Dynamically Generated IL

0.00/5 (No votes)
9 Apr 2014 1  
Matrix, Quaternion and three Vector structures with IL generated at runtime to provide support for all number types.

If you decide to use this, please, post me a comment telling me your opinion. Feedback is important.

Introduction

This is a set of 5 structures that are essential for any 2D/3D graphics programming.

The structures contained within the .zip are:

  • Matrix4
  • Quaternion4
  • Vector2
  • Vector3
  • Vector4
  • MathHelper // A bonus

What's So Special About These?

As you may know, C# doesn't support the generic constraint for numbers. It would be a great addition, but, alas, it wasn't yet implemented.

And thus, you've got 3 options when it comes to solving this problem:

  1. Throw the idea out the window and just create a new version for each type you need
  2. Try the slow interface implementation that gives you the ability to do arithmetic operations on generic types
  3. Run-time generate IL

I actually went with the first one at the beginning, but it wasn't sufficient. I had several versions of each struct. One used Singles, the other used Doubles, etc.. That's many pairs of structs to keep up to date. It wasn't worth it, so I gave it up.

The second approach is so slow that it just isn't viable for something like this, so out it went.

The third approach is the most painful one, but has the potential to have the same performance as compiled code and gives you the ultimate power.
If you want to add two variables, you can. Does it matter that they might not be something that supports addition? Not a bit, it'll just spit out some cryptic error. But should you be able to guarantee that those variables are always numbers, then you could do all the arithmetic you want without worrying.

Another problem arises, though, it's IL. No static typing, no comprehensible errors, no IntelliSense, nothing. And you know what? It sounded awesome, so I decided to go with it.

How it looks like:

I offer you this:

Matrix4:
  • Array
  • Backward
  • Column0
  • Column1
  • Column2
  • Column3
  • Down
  • Forward
  • Identity
  • Left
  • Right
  • Row0
  • Row1
  • Row2
  • Row3
  • Translation
  • Up
  • Add (+1 overload)
  • CreateBillboard (+1 overload)
  • CreateConstrainedBillboard (+2 overloads)
  • CreateFromAxisAngle (+1 overload)
  • CreateLookAt (+1 overload)
  • CreateOrthographic
  • CreateOrthographicOffCenter
  • CreatePerspective
  • CreatePerspectiveFieldOfView
  • CreatePerspectiveOffCenter
  • CreateRotationX
  • CreateRotationY
  • CreateRotationZ
  • CreateScale (+3 overloads)
  • CreateTranslation (+2 overloads)
  • CreateWorld (+1 overload)
  • Decompose
  • Divide (+2 overloads)
  • Equals (+1 overload)
  • explicit operator Matrix4<T>
  • explicit operator T[]
  • Invert (+1 overload)
  • Lerp (+1 overload)
  • Matrix4 (+3 overloads)
  • Multiply (+2 overloads)
  • Negate (+1 overload)
  • operator- (+1 overload)
  • operator!=
  • operator* (+2 overloads)
  • operator/
  • operator+
  • operator==
  • Subtract (+1 overload)
  • Transpose (+1 overload)

Quaternion4:

  • Array
  • Identity
  • Length
  • LengthSquared
  • Add (+1 overload)
  • Concatenate (+1 overload)
  • Conjugate (+1 overload)
  • CreateFromAxisAngle (+1 overload)
  • CreateFromRotationMatrix (+1 overload)
  • CreateFromYawPitchRoll
  • Divide (+1 overload)
  • Dot (+1 overload)
  • explicit oprator Vector4<T>
  • Invert (+1 overload)
  • Lerp (+1 overload)
  • Multiply (+2 overloads)
  • Negate (+1 overload)
  • Normalize (+1 overload)
  • operator- (+1 overload)
  • operator!=
  • operator* (+1 overload)
  • operator/
  • operator+
  • operator==
  • Quaterion4 (+3 overloads)
  • Slerp (+1 overload)
  • Subtract (+1 overload)

Vector2:

  • Array
  • Down
  • Left
  • Length
  • LengthFast
  • LengthSquared
  • One
  • Right
  • UnitX
  • UnitY
  • Up
  • Zero
  • Add (+3 overloads)
  • Barycentric (+1 overload)
  • CalculateAngle (+1 overload)
  • CatmullRom (+1 overload)
  • Clamp (+1 overload)
  • ComponentMax (+1 overload)
  • ComponentMin (+1 overload)
  • Cross (+1 overload)
  • Distance (+1 overload)
  • DistanceSquared (+1 overload)
  • Divide (+3 overloads)
  • Dot (+1 overload)
  • explicit operator Vector3<T>
  • explicit operator Vector4<T>
  • Hermite (+1 overload)
  • Lerp (+1 overload)
  • Max (+1 overload)
  • Min (+1 overload)
  • Multiply (+3 overloads)
  • Negate (+1 overload)
  • Normalize (+1 overload)
  • NormalizeFast (+1 overload)
  • operator- (+3 overloads)
  • operator!=
  • operator* (+2 overloads)
  • operator/ (+2 overloads)
  • operator+ (+2 overloads)
  • operator==
  • Reflect (+1 overload)
  • SmoothStep (+1 overload)
  • Subtract (+2 overloads)
  • Transform (+1 overload)
  • Vector2 (+5 overloads)
Vector3:
  • Array
  • Backward
  • Down
  • Forward
  • Left
  • Length
  • LengthFast
  • LengthSquared
  • One
  • Right
  • UnitX
  • UnitY
  • UnitZ
  • Up
  • Zero
  • Add (+3 overloads)
  • Barycentric (+1 overload)
  • CalculateAngle (+1 overload)
  • CatmullRom (+1 overload)
  • Clamp (+1 overload)
  • ComponentMax (+1 overload)
  • ComponentMin (+1 overload)
  • Cross (+1 overload)
  • Distance (+1 overload)
  • DistanceSquared (+1 overload)
  • Divide (+3 overloads)
  • Dot (+1 overload)
  • explicit operator Vector3<T>
  • explicit operator Vector4<T>
  • Hermite (+1 overload)
  • Lerp (+1 overload)
  • Max (+1 overload)
  • Min (+1 overload)
  • Multiply (+3 overloads)
  • Negate (+1 overload)
  • Normalize (+1 overload)
  • NormalizeFast (+1 overload)
  • operator- (+3 overloads)
  • operator!=
  • operator* (+2 overloads)
  • operator/ (+2 overloads)
  • operator+ (+2 overloads)
  • operator==
  • Reflect (+1 overload)
  • SmoothStep (+1 overload)
  • Subtract (+2 overloads)
  • Transform (+3 overload)
  • Vector3 (+5 overloads)
Vector4:
  • Array
  • Backward
  • Down
  • Forward
  • Left
  • Length
  • LengthFast
  • LengthSquared
  • One
  • Right
  • UnitW
  • UnitX
  • UnitY
  • UnitZ
  • Up
  • Zero
  • Add (+3 overloads)
  • Barycentric (+1 overload)
  • CalculateAngle (+1 overload)
  • CatmullRom (+1 overload)
  • Clamp (+1 overload)
  • ComponentMax (+1 overload)
  • ComponentMin (+1 overload)
  • Distance (+1 overload)
  • DistanceSquared (+1 overload)
  • Divide (+3 overloads)
  • Dot (+1 overload)
  • explicit operator Quaternion4<T>
  • explicit operator Vector3<T>
  • explicit operator Vector4<T>
  • Hermite (+1 overload)
  • Lerp (+1 overload)
  • Max (+1 overload)
  • Min (+1 overload)
  • Multiply (+3 overloads)
  • Negate (+1 overload)
  • Normalize (+1 overload)
  • NormalizeFast (+1 overload)
  • operator- (+3 overloads)
  • operator!=
  • operator* (+2 overloads)
  • operator/ (+2 overloads)
  • operator+ (+2 overloads)
  • operator==
  • Reflect (+1 overload)
  • SmoothStep (+1 overload)
  • Subtract (+2 overloads)
  • Transform (+5 overload)
  • Vector4 (+6 overloads)

Some methods like Equals, ToString, etc., were omitted from this list, but they are fully defined.

All of this is implemented in hand-written IL. It spans 20,000 lines of pure code and 80,000 lines total, including comments. Every single line of IL is commented with contents of the stack (for the purposes of debugging and better maintainability).

The methods are unit-tested and the performance (from the few tests I ran) should be very close to compiled code. It would be great if someone were to post a benchmark.

Final Words

I really hope this helps someone in some way. It has taken tremendous effort to create and to manage.

I have given it my best, so tell me what you think of it. I look forward to it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here