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. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Then you define parent/child relationship for your entities by yourself. Provided transform API is not for “conceptual” parent/child relationship, it's about concrete scene graph data structure: https://en.wikipedia.org/wiki/Scene_graph

    Of course their API for Transform is also poor since they are 3D engineers, not professional library writers. Just making the note that this particular your complaint is probably ill-founded.
     
  2. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    Of course, you can design your own APIs, but that's not the point.
    It's one of the badly designed API that needs be part of the overhaul if there will be one in the future. Parent/Child relationship should be independent of Transform. Currently, to get the parent object, you need to GameObject.transform.parent.gameObject. Does this look like a right design? I would vote strongly against it if have a choice.

    Unity API was very primitive when it first came out and they probably thought, ... all GameObject probably just 3d objects and by default it will all have Transform... and transform needs hierarchy...and let's throw parent/child in there.
    Containers and manager type of classes are not 3D objects and they are forced to instantiated with Transforms.

    oh well.. it really bugs me to see that we are stuck with the bad design...so low level that I keep seeing everywhere.

    What I'm hoping is that there will be some cleanup on APIs, if not, have a clear guideline so that future API's are consistent, and orgothogonal.
     
  3. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Transforms by themselves make absolutely no sense if they are not ordered in tree with bidirectional traversal (so called “scene graph”). It's parent/child specifically for traversing this tree, not to have some abstract high-level meaning. This kind of API looks very same in all libraries: Xenko, Box2D, etc. It has well-known expected meaning (like algebraic linear transforms in homogeneous coordinates): when you call get-world-transform (or its component: position, rotation, scale, does not matter) it performs series of matrix multiplication from local-transform of the child up to the root.

    (Sorry if it's unclear, I'm not a native speaker, discussing such details is a little bit hard in sense of vocabulary.)
     
  4. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487


    http://gameprogrammingpatterns.com/dirty-flag.html
     
  5. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    @Qbit86, I'm not saying Transform doen't need hierarchy. They do but parent/child should be a property of GameObject, not Transforms. Transform should get the parent/child information from GameObject, not the other way around. This way, conceptual(not 3d object) GameObject can have parent/child relationship and Transform can be an optional component. Let's not talk too much about Transform as it is not the point of my post. Cheers!
     
    starikcetin and Qbit86 like this.
  6. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    This is probably the last response on the ETA: https://forum.unity.com/threads/eta-of-floating-point-determinism.539534/#post-3559944.

    It doesn't seem like a thing you'd expect to show up before next winter (at earliest) and considering how these targets tend to drift, it's probably happening later during 2019 cycle.
     
    Antypodish and Nyarlathothep like this.
  7. Gen_Scorpius

    Gen_Scorpius

    Joined:
    Nov 2, 2016
    Posts:
    65
    I don't know if it has been mentioned or explained somewhere but what is the performance difference between using multiple floats vs the use of floatN in a burst-compiled job? Should I try to fill up my data in float4s for best performance?

    However, if I use floatN than I can't use the [Range] attribute to set different limits for the range of the individual floatN.x, .y and so on values. This would be useful to limit what the game designers can use as parameters in the inspector for ECS components with floatN variables.
     
  8. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    I suspect there is none, or maybe very little, with benefits for floatN.

    Don't know if that the case, but you can do the normal float with range in the inspector and then set it back via script to floatN.
     
  9. Gen_Scorpius

    Gen_Scorpius

    Joined:
    Nov 2, 2016
    Posts:
    65
    I also think about using a modified Range property that allows me to set min and max for the individual values and a custom inspector but it would be nice to know if the compacting of the floats is worth the effort.
     
  10. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Also, you alternatively could have an array of float. This would be surely faster in terms of performance. Inspector from what I have seen, can easily tackle arrays with ranges, if you wish. Of course option may not always be feasible, depending on how many float you want per entity component. So once we get such options (eventually?), It shouldn't be too difficult to achieve what you need.
     
  11. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
  12. stubbesaurus

    stubbesaurus

    Unity Technologies

    Joined:
    Oct 7, 2016
    Posts:
    3
    @Gen_Scorpius floatN maps directly to the underlying SIMD types. On PC this would be SSE/AVX. This means that for many operations such as addition, multiplication, etc, performing it on a float4 is essentially the same cost as doing it on a single float. You definitely want to leverage floatN when you are performing the same operation on all the elements of the vector. Burst will try to automatically roll float values into float4 operations, but unless your data is laid out carefully it might end up not being worth it due to all the shuffling and repacking involved to convert to and from float4. Generally you want to keep things in floatN whenever possible to avoid needless shuffles.
     
    Ofx360 and laurentlavigne like this.
  13. xoofx

    xoofx

    Unity Technologies

    Joined:
    Nov 5, 2016
    Posts:
    418
    The math library will be compatible with deterministic mode in the future (note that deterministic mode will be only available from burst, not when running withing C# (though we will have to workout this as well).

    About deterministic mode, it has been postponed for preview likely next year (hopefully within Q1/Q2, but can't tell exactly)
     
    twobob and Nyarlathothep like this.
  14. NearAutomata

    NearAutomata

    Joined:
    May 23, 2018
    Posts:
    51
    I wasn't sure where to ask this question, so I decided to post it here. Players in my game can currently navigate in eight directions using WASD as usual. In order to prevent double the movement speed when moving diagonally I am normalizing the direction vector before multiplying it with deltaTime and my movement speed constant. After moving to the Job system and the new math library I noticed an unexpected behaviour.

    Usually
    new Vector3(0, 0, 0).normalized
    would return
    (0, 0, 0)
    however
    math.normalize(math.float3(0, 0, 0))
    returns
    float3(NaNf, NaNf, NaNf)
    which isn't what I expected in the first place. This forces me to write a really weird if statement that introduces previously unnecessary branching inside of a job:
    Code (csharp):
    1. public void Execute([ReadOnly] ref PlayerController controller, ref Position position)
    2. {
    3.     var v = normalize(float3(controller.Horizontal, 0, controller.Vertical));
    4.     if (!isnan(length(v)))
    5.     {
    6.         position.Value += v * MovementSpeed * DeltaTime;
    7.     }
    8. }
    I'd like to know whether this is intended going forward or just an oversight on your end?
     
    Qbit86 likes this.
  15. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    @NearAutomata You can't really normalize a zero vector as it doesn't have any length to normalize to begin with so different math libs deal with this in different ways. Neither Vector3 or new math lib approach is ideal and both are providing a compromise, in reality you are asking it to perform a task that isn't possible, I feel that NaN is more appropriate output for such task (even though it might not be as handy for your specific use case here).

    You could try this instead:

    Code (CSharp):
    1. public void Execute([ReadOnly] ref PlayerController controller, ref Position position)
    2. {
    3.     var v = normalize(float3(controller.Horizontal, 0, controller.Vertical));
    4.     position.Value += select(v * MovementSpeed * DeltaTime, float3(0, 0, 0), isnan(v));
    5. }
     
    RaL likes this.
  16. NearAutomata

    NearAutomata

    Joined:
    May 23, 2018
    Posts:
    51
    A few days ago I read something about
    select
    in particular. Although it isn't as straightforward as writing
    position.Value += normalize(float3(...)) * Speed * dt
    (which was basically the line using old
    MonoBehaviour
    it was written that
    select
    can be optimized much better than branches using if. Don't quote me on that though.

    Thanks for this suggestion which I'll gladly incorporate in my code.
     
  17. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    This is why I suggested it (should have mentioned it separately).
     
  18. NearAutomata

    NearAutomata

    Joined:
    May 23, 2018
    Posts:
    51
    @rizu I just stumbled upon the following experimental code in the sources:
    Code (CSharp):
    1. static public float3 normalizeSafe(float3 v)
    2. {
    3.     float len = math.dot(v, v);
    4.     return math.select(new float3(), v * math.rsqrt(len), len > epsilon3f);
    5. }
     
    rz_0lento likes this.
  19. elZach

    elZach

    Joined:
    Apr 23, 2017
    Posts:
    48
    Hi, if I wanted to perform a division should I still use "/" or is there already a method in Unity.Mathematics?
    I expected to find something akin to math.div, similar to math.mul instead of "*".

    Is division just not in the library or does it use another keyword which i'm not familiar with?
     
  20. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    I suppose / is optimized as well, as multiplication. And with burst.
    However, is good practice to use multiplication rather than division, when possible.
    For example instead 5 / 100 do 5 * 0.01f

    Tehcnically you don't need div. You just invert variable, if you need divide it.
    Instead math.div (5, 27) you can do math.mul ( 5, 1/27 )
     
  21. elZach

    elZach

    Joined:
    Apr 23, 2017
    Posts:
    48
    Alright, I wasn't sure if math.mul(x,1/y) wouldn't defeat the point of not just using x/y, because you'd still use the "/" operator. But thanks for the response. :)
     
  22. NearAutomata

    NearAutomata

    Joined:
    May 23, 2018
    Posts:
    51
    Writing 1/20 for example yields a constant while math.mul(x, 1/20) of course is not a constant. Depending on the compiler and its implementation those constants won't cause overhead compared to a "div(1, 20)". So basically a math.mul(x, 1/20) will be more optimized (replaced by a high performance internal machine command) compared to a "dynamic" x/20.
     
    Alex_Galvez likes this.
  23. pvloon

    pvloon

    Joined:
    Oct 5, 2011
    Posts:
    591
    Sometimes when working with 2D angles I find I want something similair to quaternions but for 2D - aka, complex numbers.

    Any chance to adding complex numbers for use with 2D angles?
     
    vx4 likes this.
  24. georgeq

    georgeq

    Joined:
    Mar 5, 2014
    Posts:
    662
    Sounds crazy, but you might be right. A lot of people believe "Mathematics" wasn't the wisest choice for a namespace. I agree that a better decision on the namespace's name would've generated a lot less opposition and complaints.
     
    laurentlavigne likes this.
  25. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    IMO the this smaller intrinsics library should just be called Unity.Intrinsics as that's what it is. And moving things out of Mathematics that everyone expect to be in Mathematics is wrong in principle. Basically what is happening here is that you are forcing ECS package for people who want to use the new job system with Burst (but don't want to get involved with Entities yet), this isn't logical at all and will just cause more confusion among users.

    So what I'd suggest is to move the intrinsics into separate package and keep (and extend) higher level math operations on Mathematics instead.
     
  26. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    I would like to point out last two words, for now. Which makes sense, to keep mathematics library clean.

    There is no forcing involved here. We all know the whole ecs and related packages are in beta stage. So make sense to keep things away, until is decided, where they need to go.
     
    Cynicat likes this.
  27. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    863
    Is there a way to get Euler angles from quaternion or float4x4?
     
  28. slim_trunks

    slim_trunks

    Joined:
    Dec 31, 2017
    Posts:
    41
    Are there any plans to implement bilinear and even better trilinear interpolation? I know they are probably not needed as much but having a canon implementation would probably result in better performance than a less thought out version.
     
    Nyarlathothep likes this.
  29. yoonitee

    yoonitee

    Joined:
    Jun 27, 2013
    Posts:
    2,363
    The library looks good.

    One question. How do you get to the float3 vectors from a gameobject transfrom.
    Do you have to do it this way? And vice versa?

    Code (CSharp):
    1. Vector3 a = gameObject.transform.position
    2.  
    3. float3 b = float3(a.x,a.y,a.z)
    Also how do you change an array of Vector3 to an array of float3 such as:

    Code (CSharp):
    1. Vector3[] verts = mesh.triangles;
     
  30. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Code (CSharp):
    1. float3 a = gameObject.transform.position;
    float3 and Vector3 are implicitly convertible to each other.

    The second one is more tricky. I wrote a helper function that takes a managed array, allocates a native array of the same size and copies the data:
    Code (CSharp):
    1.         static unsafe NativeArray<TR> ConvertArrayToNative<TS, TR>(TS[] array) where TS : struct where TR : struct
    2.         {
    3.             Assert.AreEqual(UnsafeUtility.SizeOf<TS>(), UnsafeUtility.SizeOf<TR>());
    4.  
    5.             var native = new NativeArray<TR>(array.Length, Allocator.Persistent);
    6.             var destination = native.GetUnsafePtr();
    7.  
    8.             var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
    9.             var source = handle.AddrOfPinnedObject().ToPointer();
    10.  
    11.             UnsafeUtility.MemCpy(destination, source, array.Length * UnsafeUtility.SizeOf<TS>());
    12.  
    13.             handle.Free();
    14.             return native;
    15.         }
    16.  
    Usage:
    Code (CSharp):
    1. NativeArray<float3> array = ConvertArrayToNative<Vector3, float3>(mesh.vertices);
    It's probably not the optimal solution but works for my experiments.
     
    Last edited: Oct 28, 2018
    xman7c7 and yoonitee like this.
  31. yoonitee

    yoonitee

    Joined:
    Jun 27, 2013
    Posts:
    2,363
    I wonder how efficient that is:
    Code (CSharp):
    1. float3 a = gameObject.transform.position;
    What I would suggest is that on game object there could be a property called "nativeTransform" which outputs all the values as native values.
    Or indeed on the transform property there could be properties called "nativePosition" etc.
    And indeed on the mesh there should be a property called nativeVertices.

    Even better, there could be a property called doubleTransform which contains transform in terms of doubles instead of floats. Which might be used in the future for more precision.
     
  32. LazyGameDevZA

    LazyGameDevZA

    Joined:
    Nov 10, 2016
    Posts:
    143
    I think in terms of efficiency your suggestion might not be adding noticable gains. The main performance bottlenect of using that would be in the memory traversal going about, not so much the allocation of the float3 value. Having a "nativeTransform" which outputs all the values at native would incur having to keep those values updated for every single object, but accessing the position as is will only be required in a specific subset of the code that we'll write.

    What you're describing is rather having data on the existing api accessible in a format that's ECS friendly, but that's just as achievable through using implicit conversion.
     
  33. yoonitee

    yoonitee

    Joined:
    Jun 27, 2013
    Posts:
    2,363

    I don't think so. I'm assuming that in a transform component inside it is just a matrix of floats and should be able to output them however it feels. I could be wrong though.
     
  34. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You are wrong. It is about memory being linear to traverse and cache friendliness. The whole point of all this is to prevent the CPU being stalled fetching memory from different locations. This takes much longer than assigning to floats.
     
  35. elZach

    elZach

    Joined:
    Apr 23, 2017
    Posts:
    48
    Hey there, I'm currently rewriting old Mathf/Quaternion code into burstable code using Unity.Mathematics.
    There are a couple of functions I was missing. Namely Quaternion.FromToRotation, Quaternion.RotateTowards, Quaternion.AngleAxis aswell as Quaternion.Angle.
    For the time being I wrote custom code to replace these functions. That code obviously won't be as optimized as the native mathematics functions. So I was wondering if there are plans for addition of these functions, or if they are already in and I just haven't found them.
     
  36. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    Consider using System.Numerics.Quaternion, for example, CreateFromAxisAngle().

    Quaternion is SIMD-enabled in .NET, not sure about Unity.
     
    elZach likes this.
  37. rz_0lento

    rz_0lento

    Joined:
    Oct 8, 2013
    Posts:
    2,361
    There's Unity.Mathematics.quaternion.AxisAngle and Unity.Mathematics.quaternion.RotateX (and Y and Z) at least on the latest Mathematics package available through Package Manager.

    Whole point of the new Mathematics library is that works nicely with Burst compiler. I don't think you'll get similar perf gains from stock things that are optimized for .NET. Burst generates native code directly. It's not generic IL code that runs after it so you can't treat it the same way.
     
    illinar likes this.
  38. yoonitee

    yoonitee

    Joined:
    Jun 27, 2013
    Posts:
    2,363
    Five years ago. I said that Unity was badly optimized and could do with some much needed optimization. Certain Unity fanboys said that I was wrong and why was I complaining about Unity and I was just using it wrongly and that I didn't know what I was talking about!

    This year the priority of Unity is in optimizing the engine. Parts of which have been sped up by 5-10 times.

    Just came back to say "I told you so". :p
     
    Qbit86, Lurking-Ninja and FROS7 like this.
  39. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    863
    is there a float3 vector magnitude method somewhere?
     
  40. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    You can use math.length\lengthsq, or write your own extension with naming magnitude\sqrmagnitude it's very simple :)
     
    lclemens likes this.
  41. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    863
    or even more simple:
    float3 v; Vector3.Magnitude(v);
    :)
    But I'm thinking there might be something Burst optimized. math.length, that's nice, thanks.

    Also, can't figure out matrixes, if this is related to this thread. Need to convert world vector to local vector.
     
  42. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    You must multiply vector to TRS matrix of every parent.
     
  43. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    863
    I understand that, but specifically in Transform system there LocalToWorld and no WorldToLocal matrix, so can LocalToWorld be used in reverse somehow to convert it into WorldToLocal.

    I think I found it. math.inverse(float4x4)
     
  44. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    863
    upload_2018-12-25_20-4-20.png
    Comparison of two float3 returns bool3 which is also not implicitly convertible to bool. Can you add implicit conversion please (probably suboptimal)? Unless there is a better solution. I added Compare extension method for now.
    Code (CSharp):
    1. public static class float3Extensions
    2. {
    3.     public static bool Compare(this float3 a, float3 b)
    4.     {
    5.         return a.x == b.x && a.y == b.y && a.z == b.z;
    6.     }
    7. }
    By the way, when using quaternion.LookRotation with zero vector, the matrices become invalid and the rendering system throws errors. quaternion.LookRotation probably should throw an error itself because it took me a while to find that this is what messed up my transforms.

    Code (CSharp):
    1.             if (!velocity.Value.Compare(float3.zero))
    2.             {
    3.                 rotation.Value = quaternion.LookRotation(velocity.Value, new float3(0f, 1f, 0f));
    4.             }
     
    Last edited: Dec 25, 2018
  45. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    Code (CSharp):
    1. if (a.Equals(b))
    2. {
    3. }
     
    illinar likes this.
  46. illinar

    illinar

    Joined:
    Apr 6, 2011
    Posts:
    863
    lol, right. People told me I should use Equals, I never do.
     
  47. Qbit86

    Qbit86

    Joined:
    Sep 2, 2013
    Posts:
    487
    In .NET APIs the verb “Compare” is conventionally used for three-way comparison (ordering), not for just equality comparison. See IComparable<T>, IComparer<T>.

    The other consideration is that you probably want to use ε-threshold for floats. (Although then comparison starts violating transitive property of relation which could break sorting.)
     
    illinar likes this.
  48. Cynicat

    Cynicat

    Joined:
    Jun 12, 2013
    Posts:
    290
    There are actually functions in math to allow solving bool vectors. all() and any() are the most common. So your if statement would just be

    if (math.all(Velocity.value == float3.zero))

    But you could also check if any of the components where equal

    if (math.any(Velocity.value == float3.zero))

    Hope that clears things up! =3
     
  49. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    But that looks super ugly though
     
    starikcetin likes this.
  50. Cynicat

    Cynicat

    Joined:
    Jun 12, 2013
    Posts:
    290
    with "using static Unity.Mathematics.math" it becomes:
    if (all(Velocity.value == float3.zero))
    which helps readability a lot. I like the flexibility of it. becomes really useful when you think about functions that check sets of conditions. I used to have something similar for my voxel engine when checking sets of bools.
     
Thread Status:
Not open for further replies.