texel's picture

Math feature requests

Hi,

i have tried to port JigLibX to OpenTK.
I think i will not continue because i do not have the time and knowledge to do it quickly.

But here are some problems i had when i tried to port JigLibX to OpenTK:
Some math functions, are not implemented in OpenTK:

MathHelper.Clamp
MathHelper.Min
MathHelper.Max
MathHelper.ToRadians

Matrix4:
"+=" operator
and Matrix4.Add methode

Matrix4.Right;
Matrix4.Up;
Matrix4.Backward;
... and others

Vector3:
Constructor with one argument: float assigned to the 3 components
Vector3.Right;
Vector3.Up;
Vector3.Backward;
... and others

This classes are not present:
BoundingBox
BoundingSphere
Plane

There are also a lot of functions which are differents between XNA math and OpenTK (some times it is just a "ref" which is not present). Maybe it would have been great to have the same conventions and math function in OpenTK and XNA, to ease the port of all libraries which can be found on the web (because XNA will always be more used than OpenTK). But it's probably too late.

I hope it can help.


Comments

Comment viewing options

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

Many of these methods and classes are already a work-in-progress for OpenTK 1.1. Indeed, the idea is to bring the math API as close to XNA as possible but there's a lot of other stuff that requires attention and progress is rather slow. Any help appreciated!

Two suggestions:

  • Mono.XNA contains an implementation of the XNA math library that can be used standalone. You can use this to compile JigLibX - add some conversion operators and you'll be able to use it with OpenTK.Math transparently.
  • Matali Physics is a physics library that supports OpenTK, XNA and SlimDX out of the box. Worth a try!
texel's picture

Does it mean that you will break compatibility between the current version of OpenTK and the next ?

A lot of things have to be modified.

the Fiddler's picture

Actually, most of the work involves missing classes/methods. My working copy of the OpenTK demo contains much of this work while using a vanilla OpenTK.dll - which means the changes are purely additive.

The plan is to maintain backwards compatibility throughout the 1.x series, starting with the 1.0 betas. If this means we'll have to settle for 95% compatibility with XNA math in the end, so be it (95% is still better than what we have now).

texel's picture

ok.
If i find the time, maybe i will try to write some code.

cody's picture

I have modified OpenTK and JigLibX so they work together. On the OpenTK side it just needed some additions to the Math classes. The only thing that needed to be modified are the Vector3.Min and Vector3.Max functions as they do different things in XNA.

Maybe it would be good to merge the changes to OpenTK. Its quick&dirty right now but it shouldnt break anything that isnt using Vector3.Min/Max.(but i think they should be changed anyway, they behave really strange in OpenTK)

I only tested box collisions which work ok, see a video here:
http://www.youtube.com/watch?v=3pCRXFXeFN4

c2woody's picture

That Min/Max are indeed interesting implementations in OpenTK, though quite logic they are different from XNA and afaik the goal of OpenTK's math library was to have a similar interface as XNA (component-wise Min/Max if I understand the docs correctly??).

the Fiddler's picture

Take a look into Mono.GameMath, which is a proper, XNA-compatible, SIMD-accelerated and unit-tested math library. I will probably switch OpenTK to that once it matures (keeping the old library in a separate assembly for backwards compatibility).

Tal's picture

I just gonna open a new topic and then I saw this one.
OpenTK have a method to convert Quaternion to Matrix4, but not opposite.
I have a method for Matrix4->Quaternion that I would like that OpenTK implicit it.
Here it is(see notes):

/// <summary>
 
/// Create a <cref>OpenTK.Quaternion</cref> from a rotation <cref>OpenTK.Matrix4</cref>.
 
/// </summary>
 
/// <param name="matrix">The source of the rotation matrix.</param>
 
/// <param name="result">The output target for the result.</param>
 
/// <remarks>
 
/// This method is based on the code here:
 
/// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
 
/// </remarks>
 
public static void FromMatrix4(ref Matrix4 matrix, out Quaternion result)
 
{
 
	float halfScale;
 
	float oneOverScale;
 
	// We will calculate oneOverScale by knowing that:
 
	// 0.5 / halfScale = 0.5 / ( 0.5 * Scale ) = 1 / Scale.
 
 
 
	// The goal of those if & else blocks is to avoid square root( = scale) of a nagitive number.
 
	// We do it by swapping each element by the other if needed.
 
    if ((matrix.M11 + matrix.M22 + matrix.M33) > 0.0F)// If trace > 0, it is the simplest case.
 
    {
 
        halfScale = (float)System.Math.Sqrt((double)(matrix.M11 + matrix.M22 + matrix.M33 + 1.0F));
 
        oneOverScale = 0.5F / halfScale;
 
		// In that case, XYZ is the vector, and W is the scale.
 
        result = new Quaternion((matrix.M23 - matrix.M32) * oneOverScale,
 
            (matrix.M31 - matrix.M13) * oneOverScale,
 
            (matrix.M12 - matrix.M21) * oneOverScale, halfScale * 0.5F);
 
        return;
 
    }
 
	//And the non-friendly cases...
 
 
 
	//else
 
    if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
 
	{
 
        halfScale = (float)System.Math.Sqrt((double)(1.0F + matrix.M11 - matrix.M22 - matrix.M33));
 
        oneOverScale = 0.5F / halfScale;
 
        result = new Quaternion(0.5F * halfScale, (matrix.M12 + matrix.M21) * oneOverScale,
 
            (matrix.M13 + matrix.M31) * oneOverScale, (matrix.M23 - matrix.M32) * oneOverScale);
 
        return;
 
    }
 
	//else
 
    if (matrix.M22 > matrix.M33)
 
    {
 
        halfScale = (float)System.Math.Sqrt((double)(1.0F + matrix.M22 - matrix.M11 - matrix.M33));
 
        oneOverScale = 0.5F / halfScale;
 
        result = new Quaternion((matrix.M21 + matrix.M12) * oneOverScale, 0.5F * halfScale,
 
            (matrix.M32 + matrix.M23) * oneOverScale, (matrix.M31 - matrix.M13) * oneOverScale);
 
        return;
 
    }
 
	//else
 
    halfScale = (float)System.Math.Sqrt((double)(1.0F + matrix.M33 - matrix.M11 - matrix.M22));
 
    oneOverScale = 0.5F / halfScale;
 
    result = new Quaternion((matrix.M31 + matrix.M13) * oneOverScale, (matrix.M32 + matrix.M23) * oneOverScale,
 
        0.5F * halfScale, (matrix.M12 - matrix.M21) * oneOverScale);
 
}

As said in the code, I took it from: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matri...

And I think that OpenTK should have that method too in Matrix:

#region Multiply Functions
 
 
 
/// <summary>
 
/// Multiplies a matrix by a scalar.
 
/// </summary>
 
/// <param name="mat">The matrix.</param>
 
/// <param name="scale">The scalar.</param>
 
/// <returns>The result of the calculation.</returns>
 
public static Matrix4 Mult(Matrix4 mat, float scale)
 
{
 
    Mult(ref mat, scale, out mat);
 
    return mat;
 
}
 
 
 
/// <summary>
 
/// Multiplies a matrix by a scalar.
 
/// </summary>
 
/// <param name="mat">The matrix.</param>
 
/// <param name="scale">The scalar.</param>
 
/// <param name="result">The result of the multiplication.</param>
 
public static void Mult(ref Matrix4 mat, float scale, out Matrix4 result)
 
{
 
    result = new Matrix4(
 
        mat.M11 * scale, mat.M12 * scale, mat.M13 * scale, mat.M14 * scale,
 
        mat.M21 * scale, mat.M22 * scale, mat.M23 * scale, mat.M24 * scale,
 
        mat.M31 * scale, mat.M32 * scale, mat.M33 * scale, mat.M34 * scale,
 
        mat.M41 * scale, mat.M42 * scale, mat.M43 * scale, mat.M44 * scale);
 
}
 
#endregion
 
 
 
#region Divide Functions
 
 
 
/// <summary>
 
/// Divide a matrix by a scalar.
 
/// </summary>
 
/// <param name="mat">The matrix.</param>
 
/// <param name="scale">The scalar.</param>
 
/// <param name="result">The result of the division.</param>
 
public static Matrix4 Div(Matrix4 mat, float scale)
 
{
 
    Div(ref mat, scale, out mat);
 
    return mat;
 
}
 
 
 
/// <summary>
 
/// Divide a matrix by a scalar.
 
/// </summary>
 
/// <param name="mat">The matrix.</param>
 
/// <param name="scale">The scalar.</param>
 
/// <param name="result">The result of the division.</param>
 
public static void Div(ref Matrix4 mat, float scale, out Matrix4 result)
 
{
 
    result = new Matrix4(
 
        mat.M11 / scale, mat.M12 / scale, mat.M13 / scale, mat.M14 / scale,
 
        mat.M21 / scale, mat.M22 / scale, mat.M23 / scale, mat.M24 / scale,
 
        mat.M31 / scale, mat.M32 / scale, mat.M33 / scale, mat.M34 / scale,
 
        mat.M41 / scale, mat.M42 / scale, mat.M43 / scale, mat.M44 / scale);
 
}
 
#endregion
 
 
 
#region Operators
 
 
 
/// <summary>
 
/// Multiplies a matrix by a scalar.
 
/// </summary>
 
/// <param name="mat">The matrix.</param>
 
/// <param name="scale">The scalar.</param>
 
/// <returns>The result of the calculation.</returns>
 
public static Matrix4 operator *(Matrix4 mat, float scale)
 
{
 
    Mult(ref mat, scale, out mat);
 
    return mat;
 
}
 
 
 
/// <summary>
 
/// Multiplies a matrix by a scalar.
 
/// </summary>
 
/// <param name="scale">The scalar.</param>
 
/// <param name="mat">The matrix.</param>
 
/// <returns>The result of the calculation.</returns>
 
public static Matrix4 operator *(float scale, Matrix4 mat)
 
{
 
    Mult(ref mat, scale, out mat);
 
    return mat;
 
}
 
 
 
/// <summary>
 
/// Divide a matrix by a scalar.
 
/// </summary>
 
/// <param name="mat">The matrix.</param>
 
/// <param name="scale">The scalar.</param>
 
/// <returns>The result of the division.</returns>
 
public static Matrix4 operator /(Matrix4 mat, float scale)
 
{
 
    Div(ref mat, scale, out mat);
 
    return mat;
 
}
 
#endregion

Donno if you have already implicit those method in branch/trunk, but I hope that it will help OpenTK!

cody's picture

I finished porting JigLibX to OpenTK 1.0. No changes to OpenTK are required anymore.

Get it here:
https://sourceforge.net/projects/jiglibopentk/