Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

How to convert LocalToWorld to LocalToParent?

Discussion in 'Entity Component System' started by kro11, Mar 13, 2020.

  1. kro11

    kro11

    Joined:
    Sep 23, 2019
    Posts:
    95
    How to get exactly the same position/rotation after adding LocalToParent? It seams like LocalToWorld doesn't work after this. I tryed to subtract parent position from child position, but it works bad. And how to subtract quaternions then?
     
  2. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    61
    You should multiply LocalToWorld by inverse parent's LocalToWorld, if I understand your question correctly
     
    kro11 likes this.
  3. kro11

    kro11

    Joined:
    Sep 23, 2019
    Posts:
    95
    It doesn't work. Is this right?
    Code (CSharp):
    1. EntityManager.AddComponentData(volumeEntity, new LocalToParent { Value = math.mul(childLTW.Value, math.inverse( EntityManager.GetComponentData<LocalToWorld>(parentEntity).Value)) });
     
  4. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    61
    You have an entity (the would-be-child) that has LocalToWorld set up correctly. Now you want it to become a child of some other entity without changing it's world position/rotation/scale. Am I getting this right? In this case you need to also add the Parent component (with value set to parent entity) to the child entity.
    Also note that if your child entity also has Translation/Rotation/Scale the meaning of them gets changed once there is LocalToParent on the child entity. (see docs here: https://docs.unity3d.com/Packages/com.unity.entities@0.8/manual/transform_system.html)
     
  5. kro11

    kro11

    Joined:
    Sep 23, 2019
    Posts:
    95
    Yes. It looks like this is what I need. How to read this?
    1. [TRSToLocalToParentSystem] Parent: Write LocalToParent <= Translation * Rotation * Scale
    2. [TRSToLocalToParentSystem] Child: Write LocalToParent <= Translation * Rotation * Scale
    3. [LocalToParentSystem] Parent: Write LocalToWorld <= LocalToWorld[Parent] * LocalToParent
    4. [LocalToParentSystem] Child: Write LocalToWorld <= LocalToWorld[Parent] * LocalToParent
    Still wrong position. What I am doing wrong?
    Code (CSharp):
    1.  
    2. EntityManager.AddComponentData(overlapEntity, new LocalToParent { Value = float4x4.TRS(EntityManager.GetComponentData<Translation>(overlapEntity).Value, EntityManager.GetComponentData<Rotation>(overlapEntity).Value, new float3(1, 1, 1)) });
    3. EntityManager.AddComponentData(volumeEntity, new LocalToParent { Value = float4x4.TRS(EntityManager.GetComponentData<Translation>(volumeEntity).Value, EntityManager.GetComponentData<Rotation>(volumeEntity).Value, new float3(1, 1, 1)) });
    4. EntityManager.AddComponentData(overlapEntity, new LocalToWorld { Value = math.mul(EntityManager.GetComponentData<LocalToWorld>(overlapEntity).Value, EntityManager.GetComponentData<LocalToParent>(volumeEntity).Value) });
    5. EntityManager.AddComponentData(volumeEntity, new LocalToWorld { Value = math.mul(EntityManager.GetComponentData<LocalToWorld>(overlapEntity).Value , EntityManager.GetComponentData<LocalToParent>(volumeEntity).Value) });
    6.  
     
    Last edited: Mar 19, 2020
  6. YurySedyakin

    YurySedyakin

    Joined:
    Jul 25, 2018
    Posts:
    61
    My understanding: there are systems in the entities package that are responsible for fabricating the value of LocalToWorld - they are doing it every frame. There is a number of those systems. The one called LocalToParentSystem takes the value from LocalToParent and multiplies that by parent's value of LocalToWorld and puts the result into child's LocalToWorld. There is also TRSToLocalToParentSystem (if I remember correctly) that updates LocalToParent value from the values of Translation, Rotation, Scale etc... You don't need to do those calculations - systems from entities package do them for you.
     
  7. kro11

    kro11

    Joined:
    Sep 23, 2019
    Posts:
    95
    LocalToParent value doesn't affect anything. Only Translation and Rotation works after adding LocalToParent and Parent components. But I am trying to add this, and there is wrong position:

    Code (CSharp):
    1.  
    2. var ltw = math.mul(childLTW.Value, math.inverse( EntityManager.GetComponentData<LocalToWorld>(parentEntity).Value))
    3. EntityManager.AddComponentData(volumeEntity, new Translation { Value = ltw.Position });
    And this code works properly when parent entity with identity rotation. In other cases, it rotates towards the quaternion.identity :
    Code (CSharp):
    1. var newPos = -EntityManager.GetComponentData<LocalToWorld>(overlapEntity).Position + EntityManager.GetComponentData<LocalToWorld>(volumeEntity).Position;
    2. EntityManager.SetComponentData(volumeEntity, new Translation { Value = newPos });
    Any other ideas? Is it possible to somehow rotate this point to match the rotation of the parent entity?
     
  8. apaxnid

    apaxnid

    Joined:
    Nov 18, 2012
    Posts:
    34
    maybe try something like this
    Code (CSharp):
    1.  
    2. LocalToWorld parentLTW = EntityManager.GetComponentData<LocalToWorld>(parentEntity);
    3. LocalToWorld childLTW = EntityManager.GetComponentData<LocalToWorld>(childEntity);
    4.  
    5. RigidTransform localToWorld_parent = new RigidTransform(parentLTW.Value);
    6. RigidTransform localToWorld_child = new RigidTransform(childLTW.Value);
    7.  
    8. RigidTransform worldToParent = math.inverse(localToWorld_parent);
    9. RigidTransform localToParent = math.mul(worldToParent, localToWorld_child);
    10.  
    11. EntityManager.AddComponentData(childEntity, new Parent { Value = parentEntity });
    12. EntityManager.SetComponentData(childEntity, new Translation { Value = localToParent.pos });
    13. EntityManager.SetComponentData(childEntity, new Rotation { Value = localToParent.rot });
    14. EntityManager.AddComponentData(childEntity, new LocalToParent
    15. {
    16.     Value = new float4x4(localToParent)
    17. });
    18.  
     
  9. kro11

    kro11

    Joined:
    Sep 23, 2019
    Posts:
    95
    Thank you! It works perfectly.