Search Unity

Unity.Mathematics available on github

Discussion in 'Data Oriented Technology Stack' started by xoofx, Apr 10, 2018.

  1. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    7,073
    I think the documentation for Mathematics could be massively improved e.g. the math.cs file has a whole host of commands with minimal documentation on how they work.
     
  2. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    10
    I don't believe there is an equivalent, but you should be able to port your own version using Unity.Mathematics that's similar. Do you need to match the exact behavior of Mathf.SmoothDamp?
     
  3. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    77
    My use case was that I was migrating traditional mono behavior code that was using "Mathf.SmoothDamp" (for player movement) to pure ECS. So I needed similar functionality (if not exact) so that I can use in Jobs. I was able to move forward with the "math.lerp" function. But it would be nice to have similar function to "Mathf.SmoothDamp" in the "Unity.Mathematics".
     
  4. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,404
    Could you, please, add implicit conversions between int2/int3/int4 vectors and Vector2Int/Vector3Int/Vector4Int, the way you did for floatX and VectorX.
     
  5. arturmandas

    arturmandas

    Joined:
    Sep 29, 2012
    Posts:
    188
    Strongly upvoting - we could use 3D Geometry library accompanying this one.
     
    dadude123 and OndrejP like this.
  6. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    232
    What is the equivalent of Matrix4x4.MultiplyPoint ? When I use math.transform(float4x4,float3) I don't found the good result :/
     
  7. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,370
    mul(4x4, 4)?
     
  8. Sylmerria

    Sylmerria

    Joined:
    Jul 2, 2012
    Posts:
    232
    Of course the answer was simple :oops:
    Thanks ;)
     
  9. AutoRotate

    AutoRotate

    Joined:
    Aug 1, 2014
    Posts:
    125
    What is the equivalent of MoveTowards? I see, math.lerp, and step but can't find move towards.
     
  10. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,370
    You can write your own, MoveTowards is simple.
    Code (CSharp):
    1. public static Vector3 MoveTowards(
    2.       Vector3 current,
    3.       Vector3 target,
    4.       float maxDistanceDelta)
    5.     {
    6.       float num1 = target.x - current.x;
    7.       float num2 = target.y - current.y;
    8.       float num3 = target.z - current.z;
    9.       float num4 = (float) ((double) num1 * (double) num1 + (double) num2 * (double) num2 + (double) num3 * (double) num3);
    10.       if ((double) num4 == 0.0 || (double) num4 <= (double) maxDistanceDelta * (double) maxDistanceDelta)
    11.         return target;
    12.       float num5 = (float) Math.Sqrt((double) num4);
    13.       return new Vector3(current.x + num1 / num5 * maxDistanceDelta, current.y + num2 / num5 * maxDistanceDelta, current.z + num3 / num5 * maxDistanceDelta);
    14.     }
     
    AutoRotate likes this.
  11. AutoRotate

    AutoRotate

    Joined:
    Aug 1, 2014
    Posts:
    125

    Awesome! Thanks a lot!
     
  12. SebLazyWizard

    SebLazyWizard

    Joined:
    Jun 15, 2018
    Posts:
    10
    What are the equivalents to (Inverse)Transform(Direction/Point/Vector)?
    Let's say I want to transform a position to the local space of another position and then check for the differences between both positions on each axis, how would I do that in the most effective way?
     
  13. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,370
    mul space matrix and your vector (in world space).
     
    SebLazyWizard likes this.
  14. MrGuardianX

    MrGuardianX

    Joined:
    Sep 29, 2014
    Posts:
    42
    I don't think the naming comes from Shader world really. It is how HPC libraries and C style high perf libraries are written. And Unity wants us to finally move from script programmers not caring about your data to professionals. In this world, C-style dominates for historical reasons.

    Either way, I do really think the naming should obey C# rules. We incorporated this new math into our big project and code looks really odd when you stare inside a single method but half of your code is CamelCase and half is math.
     
  15. SebLazyWizard

    SebLazyWizard

    Joined:
    Jun 15, 2018
    Posts:
    10
    That worked fine for positions, but I didn't manage to create an equivalent method for (Inverse)TransformDirection.
    I need to compare directions of each axis separately, so logically a single dot product of both rotations wouldn't do the job here.
    Any ideas?
     
    Last edited: Jun 25, 2019
  16. DavidSWu

    DavidSWu

    Joined:
    Jun 20, 2016
    Posts:
    114
    The inefficient but easy way to inverse transform your direction is it is to treat it as a Vector4 with w=0 and multiply it through the 4x4 matrix or the transpose or whatever.
    This is assuming that your matrix is orthonormal.

    Hope that helps!
     
  17. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    402
    I don't see any half matrices and wonder if they are of any use (eg. half4x4)?
     
    Last edited: Jun 25, 2019
  18. SebLazyWizard

    SebLazyWizard

    Joined:
    Jun 15, 2018
    Posts:
    10
    Yea that worked.
    This is my solution if anyone is interested;
    Code (CSharp):
    1. float3[] moveDir = { new float3(1, 0, 0), new float3(0, 1, 0), new float3(0, 0, 1) };
    2. float[] dotDir = new float[3];
    3. for (int i = 0; i < 3; i++)
    4. {
    5.     var dirA = math.mul(matB, new float4(math.rotate(rotA, moveDir[i]), 0)).xyz;
    6.     var dirB = math.mul(matB, new float4(math.rotate(rotB, moveDir[i]), 0)).xyz;
    7.     dotDir[i] = math.dot(dirA, dirB);
    8. }
    There might be some room for improvement, so if you know some optimizations or even a better way to do it, please let me know!
     
  19. DavidSWu

    DavidSWu

    Joined:
    Jun 20, 2016
    Posts:
    114
    It seems like ARM64 supports half precision floating point numbers vias SIMD registers natively. Intel has hardware support for conversion to/from 16 bit floats so could store things as 16 bit and do your math operations using 32 bit floats and you would save on memory bandwidth.

    It would be wonderful if we could use 16 bit floats and have the compiler do what it can on the target architecture to perform operations. I.e. on X64 unpack on load to 32 bit, perform operations and and repack on store, and on ARM64 use the native 16 bit float registers.
    The results would be different on different platforms, but that is acceptable given that when you are using 16 bit floats you probably don't have strict precision requirements.
     
    GilCat likes this.
  20. DavidSWu

    DavidSWu

    Joined:
    Jun 20, 2016
    Posts:
    114
    Three and a half things that could help:
    - Since you are rotating the identity axises you can just use the vectors from the matrixes. You might have to use the transpose, I don't remember off hand if vectors are stored row major or column major.
    - the Dot product is the same for two equally rotated vectors as for unrotated vectors so you can skip the multiply by matB.
    - Since it is such a simple operation you probably don't want to create garbage with dotDir, and you might as well unroll the loop.
    Something like:
    Code (CSharp):
    1. var dotDir0 = math.Dot(rotA.c0,rotB.c0);
    2. var dotDir1 = math.Dot(rotA.c1,rotB.c1);
    3. var dotDir2 = math.Dot(rotA.c2,rotB.c2);
    If that doesn't work transpose both matrices and repeat ;)
     
    SebLazyWizard likes this.
  21. MixGrey

    MixGrey

    Joined:
    Dec 23, 2014
    Posts:
    5
    Is there a vector projection method in the library similar to Vector3.Project?
     
  22. SebLazyWizard

    SebLazyWizard

    Joined:
    Jun 15, 2018
    Posts:
    10
    For some reason that didn't work well, the positions were still effected by the world space.
    I decided to skip the matrix part and do the transformation by using the positions and rotations only, that worked fine;
    Code (CSharp):
    1. var localOffset = math.rotate(math.inverse(rotB), posA - posB);
     
  23. DavidSWu

    DavidSWu

    Joined:
    Jun 20, 2016
    Posts:
    114
    dot(vector,onNormal)/onNormal.LengthSquared()*onNormal
    Or skip the divide if onNormal is normalized
     
    MixGrey likes this.
  24. DavidSWu

    DavidSWu

    Joined:
    Jun 20, 2016
    Posts:
    114
    I may have misunderstood what you were doing. I hope that I didn't lead you astray.
    If this is performance critical and you posted more source I might be able to optimize it.
     
  25. SebLazyWizard

    SebLazyWizard

    Joined:
    Jun 15, 2018
    Posts:
    10
    Well I work on a VR game in which you can grab a weapon at any given point and orientation. In order "attach" the weapon to the hand (at the grabbed position) I need to get the position and rotation of the weapon relative to the hand that grabbed it ofc.
    Anyway that's the grab system, it all works fine, but optimization is always welcome;)

    Code (CSharp):
    1. [UpdateAfter(typeof(AgentMoveSystem))]
    2. public class AgentGrabSystem : ComponentSystem
    3. {
    4.     protected override void OnUpdate()
    5.     {
    6.         Entities.WithAllReadOnly<AgentTag>().ForEach((Entity agent) =>
    7.         {
    8.             Entities.ForEach((Entity hand, ref Translation position, ref Rotation rotation, ref Parent parent, ref AgentBone bone, ref AgentGrab grab, ref HandItem item) =>
    9.             {
    10.                 if (parent.Value != agent)
    11.                     return;
    12.  
    13.                 var handCenter = position.Value + math.rotate(rotation.Value, VrData.handCenter);
    14.                 var curHand = bone.Value - 1;
    15.                 if (grab.cur && !grab.last)//grabbing
    16.                 {
    17.                     var start = position.Value - math.rotate(rotation.Value, new float3(0, 0, 0.075f));
    18.                     var end = position.Value - math.rotate(rotation.Value, new float3(0, 0, 0.05f));
    19.                     item.Item = SphereCast(start, end, 0.075f);
    20.                     Debug.Log("hand:" + curHand + " grabbed entity:" + item.Item);
    21.  
    22.                     if (item.Item != Entity.Null)
    23.                     {
    24.                         var curItemPos = EntityManager.GetComponentData<Translation>(item.Item).Value;
    25.                         var curItemRot = EntityManager.GetComponentData<Rotation>(item.Item).Value;
    26.                         item.offsetPos.z = math.rotate(math.inverse(curItemRot), handCenter - curItemPos).z;
    27.                         item.offsetRot = quaternion.identity;
    28.  
    29.                         //flip
    30.                         if (math.dot(math.rotate(rotation.Value, new float3(0, 1, 0)), math.rotate(curItemRot, new float3(0, 1, 0))) < 0)
    31.                         {
    32.                             item.offsetRot = quaternion.RotateZ(math.PI);
    33.                             Debug.Log(curHand + " flip");
    34.                         }
    35.                         //upside down
    36.                         if (math.dot(math.rotate(rotation.Value, new float3(0, 0, 1)), math.rotate(curItemRot, new float3(0, 0, 1))) < 0)
    37.                         {
    38.                             item.offsetRot = math.mul(item.offsetRot, quaternion.RotateY(math.PI));
    39.                             Debug.Log(curHand + " upside down");
    40.                         }
    41.                         Debug.Log("hand:" + curHand + " offsetPos:" + item.offsetPos /*+ " X:" + dotDir[0] + " Y:" + dotDir[1] + " Z:" + dotDir[2]*/);
    42.                     }
    43.                 }
    44.                 else if (!grab.cur && grab.last)//releasing
    45.                 {
    46.                     item.Item = Entity.Null;
    47.                     item.offsetPos = float3.zero;
    48.                     item.offsetRot = quaternion.identity;
    49.                     Debug.Log("hand:" + curHand + " released");
    50.                 }
    51.             });
    52.         });
    53.     }
    54. }
     
    Last edited: Jul 11, 2019
  26. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    10
    I've been thinking about whether or not we should make half4x4 available but the main challenge is storing positions. A half precision float really isn't precise enough to be able to store positions in that format except for very specific circumstances which limits the use case for half4x4.
     
    GilCat likes this.
  27. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    402
    How bad would it be to convert a float4x4 to half4x4?
    My use case is to use them to as the structures to upload into a compute buffer in order to reduce the amount of data as opposed to upload a float4x4.
    I've done a naive implementation of half4x4 to that purpose and convert my LocalToWorld float4x4 and the last possible moment.
     
  28. dyox

    dyox

    Joined:
    Aug 19, 2011
    Posts:
    531
    Hello,

    I'm using jobs + mathematics with noises and i'm having float precision issues.
    It is planned to implement double for noises ? (double2 / double3)
     
  29. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    10
    Can you elaborate more on what issues you're having?
     
  30. Dale_Kim

    Dale_Kim

    Unity Technologies

    Joined:
    May 8, 2019
    Posts:
    10
    That depends on what those 4x4 matrices need to hold and the range of values they need to support. If you're dealing with something with very little translation from the origin and don't require a ton of precision for the rotation, then it's probably OK. Can you share more on what you're doing and what range of values you expect in those matrices?
     
  31. GilCat

    GilCat

    Joined:
    Sep 21, 2013
    Posts:
    402
    In all my entities i use LocalToWorld component (which has float4x4) and in the very last moment of setting the ComputeBuffer i convert the float4x4 to half4x4.
    The ranges can be anything since it follows the Transform System rules.
    This is all part of a Sprite Render system and the shader used expects uint values on its StructuredBuffer (See attached shader).
    So far i haven't seen any problems using this and as mentioned before setting the compute buffer data is way faster.
     

    Attached Files:

  32. pragmascript

    pragmascript

    Joined:
    Dec 31, 2010
    Posts:
    72
    For our game we split some code into a seperate Visual Studio Solution as a managed plugin.
    (So we can use the same code for client- and serverside unity projects)

    We wanted to use Unity Mathematics everywhere. But it is unclear how we can add a reference to the Unity Mathematics package for a standalone VS Solution. AFAIK there is no compiled DLL version of the library that we can just reference (as we do with UnityEngine.dll)

    So what would be recommended practice if we want to use Unity Mathematics both inside of Unity as a package as well as in custom managed plugins?
     
  33. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,314
    Library/ScriptAssemblies. This keeps your shared project automatically in sync with what you are using on the Unity side.
     
    pragmascript likes this.
  34. pragmascript

    pragmascript

    Joined:
    Dec 31, 2010
    Posts:
    72
    Oh nice I didn't know about that one :) thanks
     
  35. m3rt32

    m3rt32

    Joined:
    Mar 5, 2013
    Posts:
    58
    I have a question/request. Is it possible to have swizzling like we have in shader languages ? It is very useful and I feel like it can be a nice addition to math library.
     
  36. recursive

    recursive

    Joined:
    Jul 12, 2012
    Posts:
    584
    @m3rt32 - if you mean per-component swizzles all of the PRIMITIVE[N] types support this already, with things like .xxxx, .xy .zw, etc. It's all auto-generated C# code.
     
  37. m3rt32

    m3rt32

    Joined:
    Mar 5, 2013
    Posts:
    58
    Oh, my bad. This is awesome. Suddenly this math library became my favorite :D