george's picture

Math module?

On the source force page, it's mentioned that OpenTK contains a maths module. Is this accurate? I don't see it anywhere.


Comment viewing options

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

Ok, I think most things have been answered, but I might as well explain some more, just to clear up any confusion.

Generally the functions have two versions. One that looks like this:

public static Vector3 Operation(Vector3 a, Vector3 b)

in which the operands are passed by value (they're structs), that is they are copied onto the stack. we reuse one of those copies to hold the result so we don't need to call new and make a third copy. this is then returned by value, ie copied back.

The second version looks like this:

publci static void Operation(ref Vector3 a, ref Vector3 b, out Vector3 result)

here the operands are passed by reference. no copy is made on the stack (so it's a little bit faster), the result can't possibly be null (it's a struct remember), so we can just write the result into it. no temporary copies are made and nothing is copied back to the caller.

the operator overloads are basically the same as the first version (ie pass by value).

To answser Inertia's original point 3:
There's no chance of the result parameter being null so we don't need to call new, and the function bodys are so trivial that the small amount of code duplication is preferable to making a function call and relying on the jit to inline it. The definition of a cross product is not likely to change any time soon :) same goes for the operator overloads.

hope that clears things up.

Inertia's picture

1) If you decide to let the programmer handle special cases like this, please throw an Exception("Matrix is singular and cannot be inverted.") or something like that at Matrix4.cs Line: 437. The code block is currently:

435  if (pivot == 0.0f)
436  {
437   	return mat;
438  }

4) Doh. Yes, you are absolutely right and I have to apoligize for wasting your time. I had used classes and derived Vector2/3/4 from a Vector base class to avoid duplicate functions, and was so excited about your announcement that I didn't really look at your definition and jumped right into the implementation part. Please consider 4) void and null. I think your decision to use structs is better in this case, the amount of duplicate code is still manageable and the complexity of the Vector structs is limited.

I'll download and work with the math library a bit before making any further comments, promised ;)

the Fiddler.'s picture

Good catch, corrected!

Axelill's picture

Just a question is

public void Normalize()
            float scale = 1.0f / this.Length;
            X *= scale;
            Y *= scale;
            Z *= scale;

better than

public void Normalize()
            float scale =  this.Length;
            X /= scale;
            Y /= scale;
            Z /= scale;

Is multiply quicker than divide ?

Anyway, this is really a good work.

If people want to use their own implementation, it 's easy to rewrite the part and compile to get exactly what you want and need.

I'm really happy with this structures (at least the vector 2,3 and 4 (have not looked the matrix)) and should do the job that 90% of the users want.


edit : now, I've checked the matrix structure and I have two questions :
- first why 4 vector instead of float[16] (reuse code of vecotr4 ?) it would have been better for a GL.LoadMatrix(ref Matrix4 m) or something. I'm sure there is a reason why using 4 vector but I can't find why ? ;)
- second why 4 ROW vector :
I though opengl was using column matrix :
now, let's check the quaternions.

george's picture

Yes, multiply is generally a lot faster than divide. enough to make it worthwhile to precompute the reciprocal and multiply if you're doing more than one.

as for the matrix, arrays aren't value types in c# so having an array of matrices wouldn't lay them out how you want. It makes the implementation simpler as well. They could have been rows or columns, but the row layout is more common I think.

Axelill's picture

Not an array of matrices but more something like :

struct Matrix
private float[] m_matrix = new float[16];

If you use the column matrix (opengl) instead of the row matrix(most used), then it is easy to overload Gl.LoadMAtrix(Matrix m) (normaly glLoadMAtrix(const float*)in C)
because the 4 vector will be aligned in the memory instead with row vector the memory allocation is no good(not good for opengl).

DIrectX use row matrix because every function in directx is made for row matrix.
Opengl use collumn matrix so it would give more possibilities of improvement for the future.

Correct me if i'm wrong.

PS : and there is a lot of function in opengl that use the const float* as a matrix;


the Fiddler.'s picture

OpenGL can use row-major matrices too, with glLoadTransposeMatrix, so the choice of one over the other has little impact. It's been some time before I touched matrix code, but I think some things can be implemented easier with row-major matrices (but don't quote me on this :) )

About const float * parameters, it makes no difference if you declare an array of 16 floats vs 4 Vector4's, as long as long as the layout in memory is the same (and it is, since Matrix4 is declared with the the StructLayout(LayoutKind.Sequential) attribute). Both cases will (should) work if you pass the address of the first element.

Axelill's picture

Yes, true the problem with transposeMatrix is if the matrix is not normalised (not often) it's just a pain in the ass for the computer to use it and even tranpose matrix, i think ( but do not quote me for this ;)) that he just move the value to fit what opengl works with (column matrix).

From The openGl Bible (opengl programming guide sixth version page 116 bottom page) :

"glLoadTransposeMatrix(m) has the same effect as glLoadMtrix(transpose(t))."

So lot of useless calculation. Need to be verified but it might be the case. If someone knows more about opengl matrix management, that would be appreciated.


the Fiddler.'s picture

I just read (but didn't verify) that the ATI SDK works with row-major matrices, which might indicate that these work better on ATI hardware. The OpenSceneGraph also uses row-major matrices (the have an interesting discussion), if that means anything.

In any case, I am not going to rewrite matrix functions (don't break something that works!) and probably noone else will. It's way too much work for the benefit of using one OpenGL function over another. :)

Axelill's picture

ok cool. just wanted to know. It was more a "I need to know" problem than" I want you to rewrite everything" problem. ;)

Good work and thanks for everything - learn every day on opengl with opentk ;)

Let's change my code with vector3 and matrix and see what it does.