Search Unity

Official Unity.Mathematics available on github

Discussion in 'Entity Component System' started by xoofx, Apr 10, 2018.

Thread Status:
Not open for further replies.
  1. LazyGameDevZA

    LazyGameDevZA

    Joined:
    Nov 10, 2016
    Posts:
    143
    I think the point @eizenhorn is trying to make is that the
    Angle
    method is either returning a value that would be greater or equal to
    float.Epsilon
    . While the check in the
    RotateTowards
    method could also be expressed as
    num <= 0.0f
    the way that num is calculated means there had already been a tolerance comparison and the expected value don't need any further tolerance checking, but there was a stylistic choice to show that this value has the potential to only ever be 0.0f and further tolerance isn't needed.

    That said I'd also rather use what @eizenhorn is using because to me it's a little more expressive and seeing the usage of
    float.Epsilon
    I'm reminded that single floating-point math comparisons can be complicated and it can serve as a start-point for somebody reading through the code. If they don't quite understand the implications of doing equality checking without adding tolerance the mention of
    float.Epsilon
    should at least indicate to them what precisely is going on here.

    One could argue that they're just trying to hide a compiler warning, but at least to me, this makes it slightly more obvious that the expected result should actually be 0 and not a simple coding error that that had been suppressed.
     
    eizenhorn and Sylmerria like this.
  2. Awarisu

    Awarisu

    Joined:
    May 6, 2019
    Posts:
    215
    My problem/worry is that float.Epsilon is a noob trap. You think you're doing everything correctly by applying tolerance, the compiler/ReSharper/what-have-you are silenced, but in fact you are checking for (in)equality to 0.0f just in a roundabout way. Something like Mathf.Approximately does this correctly, taking magnitudes into account (it's just misdocumented to imply that it only checks if the values are within Epsilon of each other, I've reported this inaccuracy months ago but of course it hasn't been fixed...)
     
    amarcolina likes this.
  3. amarcolina

    amarcolina

    Joined:
    Jun 19, 2014
    Posts:
    65
    Some relevant parts of the official docs for float.Epsilon (LINK)

    Represents the smallest positive Single value that is greater than zero.​

    If you create a custom algorithm that determines whether two floating-point numbers can be considered equal, you must use a value that is greater than the Epsilon constant to establish the acceptable absolute margin of difference for the two values to be considered equal. (Typically, that margin of difference is many times greater than Epsilon.)
    There is no value that is smaller than float.Epsilon and larger than zero, by definition.
     
    Awarisu likes this.
  4. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    I have not yet added this and it would be simple to add, but are you looking for serializable so that it can be exposed in the inspector or to be able to write the half data to disk?
     
  5. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    Both would be nice, but save to disk is far more important.
     
  6. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    Usage of float.Epsilon is highly discouraged in Unity code. The reason is that float.Epsilon is a denormal (aka - subnormal) float and many platforms either do not support these floats and flush those values to zero or other code may change the denormal handling mode of the CPU and you may start seeing float.Epsilon as zero even though a prior use of that constant was correctly handled as non-zero.

    In the case where denormals are not handled and flushed to zero, your code is actually behaving as:

    Code (CSharp):
    1.  
    2. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    3. public static quaternion RotateTowards(
    4.     quaternion from,
    5.     quaternion to,
    6.     float maxDegreesDelta)
    7. {
    8.     float num = Angle(from, to);
    9.     return num < 0.0f ? to : math.slerp(from, to, math.min(1f, maxDegreesDelta / num));
    10. }
    11.  
    Simplified:

    Code (CSharp):
    1.  
    2. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    3. public static quaternion RotateTowards(
    4.     quaternion from,
    5.     quaternion to,
    6.     float maxDegreesDelta)
    7. {
    8.     float num = Angle(from, to);
    9.     return math.slerp(from, to, math.min(1f, maxDegreesDelta / num));
    10. }
    11.  
    This is because the minimum value that Angle() will ever return is 0 and 0 < 0 is never true.
     
  7. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    Are you storing the half type inside some managed object which you're serializing?

    We expected users of the half type to use these in blittable types and then write out memory buffers directly to disk, but if you're saving them in managed objects then I see why you need that serializable attribute.
     
  8. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    Code (CSharp):
    1.  
    2. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    3. public static quaternion RotateTowards(
    4.     quaternion from,
    5.     quaternion to,
    6.     float maxDegreesDelta)
    7. {
    8.     if (maxDegreesDelta <= 0) return from;
    9.     float num = Angle(from, to);
    10.     if (maxDegreesDelta >= num) return to;
    11.     return math.slerp(from, to, maxDegreesDelta / num);
    12. }
    13.  
    There, now you don't need to worry about epsilon.
     
    Last edited: Mar 5, 2020
  9. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    Animation data from an Editor tool that needs to live somewhere in the project until it can be copied to a ComputeBuffer.
     
  10. sand_lantern

    sand_lantern

    Joined:
    Sep 15, 2017
    Posts:
    210
    I know it's a fairly trivial calculation, but is there some built in way to get the cross product of a (float2x2 * float2)? I looked at the multiplication operators and math.cross() function and neither of them are giving me what I want.

    For reference, my use case is I'm translating a point via a basis vector from world space to a hex grid location. Seems like that is a common enough use that it should be another overload for these cases somewhere.
     
  11. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    Sorry, I don't follow what you mean by the cross product of a (float2x2 * float2). It seems to me that you're saying a cross product of a float2. Can you write out the full mathematical expressions you expect to be able to achieve?
     
  12. sand_lantern

    sand_lantern

    Joined:
    Sep 15, 2017
    Posts:
    210
    Sorry, it's been a long time since my uni days and I may have gotten my terminology mixed up. The formula specifically I'm doing is outlined here https://www.redblobgames.com/grids/hexagons/#pixel-to-hex
    Currently I have this equation in code.

    Code (CSharp):
    1. private static float2 Multiply (float2x2 basis, float2 point)
    2. {
    3.     return new float2 (
    4.         x: basis.c0.x * point.x + basis.c1.x * point.y,
    5.         y: basis.c0.y * point.x + basis.c1.y * point.y);
    6. }
    I know you can't have every case available, but these scenarios seem like a pretty common one to me.
     
  13. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    math.mul
    ?
     
    sand_lantern likes this.
  14. sand_lantern

    sand_lantern

    Joined:
    Sep 15, 2017
    Posts:
    210
    Ah, interesting. I guess I was looking for an operator or function on the type itself when I should have been looking in there. That seems fine, just different than where I expected.

    Never mind me.
     
  15. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    elliotc-unity and ecurtz like this.
  16. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    Hi @Dale_Kim, have u implement Linear congruential generator, Mersenne Twister and etc RNG algorithms into Unity.Mathematics package? I would like to see the package has variety of RNG algorithms to use out of the box.
     
  17. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    883
    Double Quaternions would be great. They are must have for any space simulator. And since you already have double vectors and matrices, why not Quaternions?
     
  18. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    I'm scheduled to implement LCG as a random number generator soon!

    Mersenne twister is not going to be implemented due to its state size but others may be implemented in the future.
     
    _met44 and Sylmerria like this.
  19. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    Do you have specific case where a single precision float based quaternion is not sufficient for such a space simulator?
     
  20. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    883
    I have a game: https://store.steampowered.com/app/890520/How_do_you_like_it_Elon_Musk/
    where I have a Solar System in real scale. So I needed quternion3d in at least three places: generating planet surfaces (quadtree is splitted up to 17 level), rotating planets, and also for rocket auto stabilization system, which rotates spacecraft to prograde/retrograde etc vectors (velocity vectors are huge on the orbit of such scale).
     
  21. optimise

    optimise

    Joined:
    Jan 22, 2014
    Posts:
    2,129
    What state size means? Do you mean its memory consumption is quite high and random generation is quite slow too?
     
  22. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    792
    I'm not an expert on quaternions, but quaternions are about rotation and orientation, not distance. So float should be precise enough?
     
  23. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,776
    Further you want to look ahead, the greater error of the angle, with low enough precision.



    If your sun is of a pixel size and your angle is only 1 degree precision (as an example), at certain distance error can be so great, you can miss sun, between angular step. But in games, there are tons of simplifications and approximations, hence no need for such high precision.
     
  24. ecurtz

    ecurtz

    Joined:
    May 13, 2009
    Posts:
    640
    I originally misread Antypodish's request for double quaternions as a request for dual quaternions, so if you're considering more things to add quaternion2 is used in some systems for more accurate skinned characters...
     
  25. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    883
    If it was precise enough I wouldn't write anything here.
    When you are generating the planet, you eventually need to multiply your double3 to quaternion. And you need to cast it to float3 and loose all precision and get cracks on the surface. Or you need quaterniond. Also for planet rotation even with planets as small as in KSP you already need this, especially for planets with long rotation period.
     
  26. Ramobo

    Ramobo

    Joined:
    Dec 26, 2018
    Posts:
    212
    Quite late to the party, but we can dream.
     
    hippocoder likes this.
  27. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    792
    If I remember correctly, KSP has its own quaterion implmentation for doubles.
     
  28. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    883
    Yea, I have too. I just copy pasted quternion from the Unity.Mathematics and replaced floats with doubles. But since the Unity.Mathematics code is based on codegen in there are double vectors and matrices already, I think it would be very convenient to add double quaternions too. I really see no good reasons why not.
     
    sand_lantern likes this.
  29. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    Mersenne twister uses 2.5 KB of internal state to generate its random numbers. It is a performance requirement for Unity.Mathematics random number generators to be 32 bits of state so that way random number generation can easily be vectorized.
     
    hippocoder and optimise like this.
  30. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    Would it be possible for you to provide some example calculations (including values) you were using with a single precision float quaternion that failed to achieve the quality you were looking for? I would love to dig in to see where the issues are.
     
    hippocoder likes this.
  31. Extrys

    Extrys

    Joined:
    Oct 25, 2017
    Posts:
    345
    is there any diference between quaternion and Quaternion or RigidBody.AngularVelocity and PhysicsVelocity.angular?
    what i need to know to operate conversions?
     
  32. LazyGameDevZA

    LazyGameDevZA

    Joined:
    Nov 10, 2016
    Posts:
    143
    There's a difference in where the types originate from. Quaternion and RigidBody.AngularVelocity lives as part of the original UnityEngine. quaternion is part of the Unity Mathematics package and PhysicsVelocity is part of the Unity Physics package. The package variations serve the same purpose of the UnityEngine variations, but the big difference is that the package variations have better Burst compilation support, well that's my understanding of it.

    As far as I know the Unity Mathematics package does include implicit casting operations to and from the Unity Engine types, but this does mean it isn't completely clear which type is used where. Take the following code as an example:


    Code (CSharp):
    1. Vector3 unityPosition = new Vector3(1,2,3);
    2. float3 packagePosition = new float3(1,2,3);
    3.  
    4. // This is ambiguous
    5. var ambiguousResult = unityPosition + packagePosition;
    While I haven't tested this code, my gut is telling me it won't compile because the compiler won't know if it should use the
    float3
    + operator or the
    Vector3
    + operator. The main point is you'll have to be explicit with the types of your variables to be sure which one to use where.
     
  33. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    883
    It will require to strip down the part of planet generation system of the game. Or I will try to prepare another example. Anyway I will pm you when it will be ready.
     
  34. Extrys

    Extrys

    Joined:
    Oct 25, 2017
    Posts:
    345
    anyone does know why rotations in DOTS
    behaves diferent from MonoBehaviour transforms?

    MonoBehaviour
    Code (CSharp):
    1.  
    2. Quaternion delta = targetTransform.rotation * Quaternion.Inverse(transform.rotation);
    3. delta.ToAngleAxis(out float angle, out Vector3 axis);
    4. if (float.IsInfinity(axis.x)) return;
    5.  
    6. rigidbody.angularvelocity  = axis * (angle * Mathf.Deg2Rad / Time.deltaTime);

    DOTS
    Code (CSharp):
    1.  
    2. float4 delta = mul(ltw.Rotation, inverse(thisLtw.Rotation)).value;
    3. float len = sqrt(delta.x * delta.x + delta.y * delta.y + delta.z * delta.z);
    4.  
    5. float angle = 2 * atan2(len, delta.w);
    6. float3 axis = select(float3(1, 0, 0), delta.xyz / len, len > 0);
    7.  
    8. vel.Angular = axis * angle / deltaTime;
    Tecnically im doing the same, but in DOTS it start jittering a lot and doing weird things after a certain angle
     
    Last edited: Mar 21, 2020
  35. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,776
    @ExtrysGO What is your deltaTime based on in DOTS version?
    How do you run Update in both examples?
     
  36. Extrys

    Extrys

    Joined:
    Oct 25, 2017
    Posts:
    345
    OnUpdate, that was inside the Entity foreach
    the delta time is saved in a variable out of entity foreach
    to be able to burst compile

    and everithing works properly until dertain initial angle, and i dont know why, i have been triyng also the normal version with UnityEngine.Quaternion and it works the same bad

    so i think there could be some diference betwen PhysicsVelocity and Rigidbody.velocity
     
  37. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,776
    @ExtrysGO I don't know if that will be any of use, but you could try to sum delta time of each approach.
    After few seconds / minute, they should be same.

    Also, maybe there is some precision los in DOTS, which causing an error? Just guessing.
     
  38. Extrys

    Extrys

    Joined:
    Oct 25, 2017
    Posts:
    345
    The problem was that DOTS angular Velocity is in Motion Space instead of Global space, unlike monobehaviours
     
  39. SirIntruder

    SirIntruder

    Joined:
    Aug 16, 2013
    Posts:
    49
    There is no method in Unity.Mathemathics to convert Quaternion into euler angles, or am I missing something?
     
  40. Extrys

    Extrys

    Joined:
    Oct 25, 2017
    Posts:
    345
    There is, you have to use the "quaternion" class
     
  41. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    There currently isn't a conversion from quaternion to Euler angles. I plan on adding a conversion for this soon!
     
    Zeffi, _met44, thelebaron and 2 others like this.
  42. Bas-Smit

    Bas-Smit

    Joined:
    Dec 23, 2012
    Posts:
    274
    Would you consider adding editor+devbuild only sanity checks to prevent things like normalizing zero length vectors? Right now this produces a bunch of nans which can cause tricky to locate issues
     
    hippocoder likes this.
  43. benblo

    benblo

    Joined:
    Aug 14, 2007
    Posts:
    476
    So we have float4.xyzw and all the possible swizzle accessors, but no float4.rgba and swizzles... given that one of the goal of Unity.Mathematics is to seamlessly swap between HLSL/GLSL code and C# code, I find that a bit odd! or am I missing something?
     
    TJHeuvel-net likes this.
  44. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    That sounds like a good idea, I'll add it to our internal bug/feature tracking database.
     
  45. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    56
    I'll be adding .rgba and their swizzles to Unity.Mathematics soon (hopefully within the next few weeks)!
     
    benblo and Sylmerria like this.
  46. Lieene-Guo

    Lieene-Guo

    Joined:
    Aug 20, 2013
    Posts:
    547
    could inversed Hyperbolic functions be added to the math lab?
    as walkaround,I am using
    Code (CSharp):
    1. namespace Unity.Mathematics
    2. {
    3.     public static partial class mathExt
    4.     {
    5.         //https://en.wikipedia.org/wiki/Hyperbolic_functions
    6.         public static float atanh(float x) => 0.5f * math.log((1 + x) / (1 - x));
    7.         public static float2 atanh(float2 x) => 0.5f * math.log((1 + x) / (1 - x));
    8.         public static float asinh(float x) => math.log(x + sqrt((x * x) + 1));
    9.         public static float2 asinh(float2 x) => math.log(x + sqrt((x * x) + 1));
    10.         public static float acosh(float x) => math.log(x + sqrt((x * x) - 1));
    11.         public static float2 acosh(float2 x) => math.log(x + sqrt((x * x) - 1));
    12.     }
    13. }
    But could there be a faster version using, for example transformed Taylor series?
    I am using these functions to solve quadratic drag dynamic.
    For like high-speed free-fall object.
     
    florianhanke likes this.
  47. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Still the case in Unity 2019.3.10 making this library 10-15 times slower than Math in il2cpp.

    Did few tests with the generated cpp:

    1. Removing IL2CPP_RUNTIME_CLASS_INIT didn't make that much difference for Mathf.Sin.

    2. Main bottleneck of Mathmatics.math.sin comes from calling the function itself, it would have to be inlined (in c++) to make it as fast as Mathf.Sin.

    Also tested Mono instead of il2cpp, incredibly slow:
    Code (CSharp):
    1. (float)Math.Sin: 263311 ticks
    2. Mathf.Sin: 378154 ticks
    3. Unity.Mathematics.math: 374139 ticks
    Tested Unity.Mathematics.math.sin + Burst vs Mathf.Sin + Burst - generated code and speed is the same.
     
    Last edited: Apr 23, 2020
  48. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Issue described above can be fixed by changing Unity.Mathematics source:

    Before:
    Code (CSharp):
    1.  
    2.         public static float sin(float x) { return (float)System.Math.Sin((float)x); }
    After:
    Code (CSharp):
    1.  
    2.         [MethodImpl( MethodImplOptions.AggressiveInlining )]
    3.         public static float sin(float x) { return (float)System.Math.Sin(x); }
    Generated cpp has inline specifier:

    Code (CSharp):
    1. IL2CPP_EXTERN_C inline  IL2CPP_METHOD_ATTR float math_sin_m7CB1E8DF153CC3E22A6C366F3F5F98571CF77BA9_inline (float ___x0, const RuntimeMethod* method)
    2. {
    3.     static bool s_Il2CppMethodInitialized;
    4.     if (!s_Il2CppMethodInitialized)
    5.     {
    6.         il2cpp_codegen_initialize_method (math_sin_m7CB1E8DF153CC3E22A6C366F3F5F98571CF77BA9NewAssembly_MetadataUsageId);
    7.         s_Il2CppMethodInitialized = true;
    8.     }
    9.     {
    10.         // public static float sin(float x) { return (float)System.Math.Sin(x); }
    11.         float L_0 = ___x0;
    12.         IL2CPP_RUNTIME_CLASS_INIT(Math_tFB388E53C7FDC6FCCF9A19ABF5A4E521FBD52E19_il2cpp_TypeInfo_var);
    13.         double L_1 = sin((((double)((double)L_0))));
    14.         return (((float)((float)L_1)));
    15.     }
    16. }
    Interesting, this means that AggressiveInlining makes huge difference in il2cpp not only for this library.

    @Dale_Kim Consider adding it to all functions in the math library.
     
    Vincenzo likes this.
  49. Vincenzo

    Vincenzo

    Joined:
    Feb 29, 2012
    Posts:
    146
  50. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    I've also already mentioned it there:
     
Thread Status:
Not open for further replies.