Posted Tuesday, 6 November, 2007 - 12:53 by george
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:
publicstaticVector3 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 staticvoid Operation(refVector3 a, refVector3 b, outVector3 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.
Posted Tuesday, 6 November, 2007 - 13:46 by Inertia
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:
435if(pivot == 0.0f)436{437return 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 ;)
Posted Tuesday, 6 November, 2007 - 17:02 by Axelill
Just a question is
publicvoid Normalize(){float scale = 1.0f / this.Length;
X *= scale;
Y *= scale;
Z *= scale;
}
better than
publicvoid 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.
Axel.
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 : http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/...
now, let's check the quaternions.
Posted Tuesday, 6 November, 2007 - 17:06 by george
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.
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;
Posted Tuesday, 6 November, 2007 - 17:59 by the Fiddler.
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.
Posted Tuesday, 6 November, 2007 - 18:21 by Axelill
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.
Posted Tuesday, 6 November, 2007 - 18:39 by the Fiddler.
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. :)
Comments
Ok, I think most things have
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:
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:
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.
1) If you decide to let the
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:
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 ;)
Good catch, corrected!
Good catch, corrected!
Just a question is public
Just a question is
better than
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.
Axel.
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 :
http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/...
now, let's check the quaternions.
Yes, multiply is generally a
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.
Not an array of matrices but
Not an array of matrices but more something like :
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;
Axel.
OpenGL can use row-major
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.
Yes, true the problem with
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.
Axel.
I just read (but didn't
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. :)
ok cool. just wanted to
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.
Axel.