Search Unity

Change from one cartesian 3D co-ordinate system to another by translation and rotation

Discussion in 'General Discussion' started by isawyou0, Apr 1, 2021.

  1. isawyou0

    isawyou0

    Joined:
    Oct 8, 2020
    Posts:
    30
    just like parent and child,

    I wanted to do it from scratch


    any math behind?
     
  2. I recommend Freya's courses on the matter. The other ones too, but what you're looking for is around this time:
     
    Antypodish likes this.
  3. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    Give me a reason to bother explaining anything to someone with this kind of attitude?

    It is not something secret, and the video is likely on point.
     
  4. isawyou0

    isawyou0

    Joined:
    Oct 8, 2020
    Posts:
    30
    sorry :p
     
  5. isawyou0

    isawyou0

    Joined:
    Oct 8, 2020
    Posts:
    30
    found this

    def change_basis(coords, new_basis, old_basis):
    '''
    Change the basis of coordinates to a new basis. In a regular structure
    we have the coordinates in the regular cartesian coordinate system. For helix-helix
    orientations, however, we want to express the coordinates in a coordinate system
    defined by the first helix.

    The new basis will consist of the axis of the first helix, one of its twist elements
    (the one closest to the second vector) and a third vector orthogonal to the previous
    two.

    # http://tutorial.math.lamar.edu/Classes/LinAlg/ChangeOfBasis.aspx

    @param coords: The coordinates to transform (array of n elements).
    @param new_basis: The new basis vectors (n x n matrix)
    @param old_basis: The old basis for the coordinates(n x n matrix)
    @return: The new coordinates according to the new basis
    '''
    #assert(len(coords) == len(new_basis))
    #assert(len(new_basis) == len(old_basis))

    dim = len(coords)
    #print "coords:", coords
    standard_coords = np.dot(old_basis.transpose(), coords)
    '''
    #print "standard_coords:", standard_coords
    standard_to_new = inv(new_basis.transpose())
    #print "standard_to_new:", standard_to_new
    new_coords = np.dot(standard_to_new, standard_coords)
    print "new_coords:", new_coords
    '''

    new_coords = nl.solve(new_basis.transpose(), standard_coords)
    #print "new_coords1:", new_coords1

    return new_coords
     
  6. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    Nope. Overly complicated and slow due using solver.

    Watch the video from earlier, and apologize to its author.
     
  7. isawyou0

    isawyou0

    Joined:
    Oct 8, 2020
    Posts:
    30
    sorry sorry I'm really sorry :( I'm crying I apologize to all of you and to the author, it's a good video, I was wrong, I thought that was a troll video, really sorry I remove what I said
     
  8. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    Good. Now, back to the topic.

    The matrix is LITERALLY basis vectors and position packed into a matrix.

    "Transform" matrix denotes how the new coordinate system is represented within the old one.
    Meaning, as long as it is not a projection matrix, a matrix stores "xAxis vector", "yAxis vector", "zAxis vector" and "position".

    The reset depends on used notation. For example, I believe directx used row major matrix layout in documentation:
    Code (csharp):
    1.  
    2. u.x u.y u.z 0
    3. v.x v.y v.z 0
    4. w.x w.y w.z 0
    5. p.x p.y p.z 1
    6.  
    So, if your matrix only translates, then it will be
    Code (csharp):
    1.  
    2.   1   0   0 0
    3.   0   1   0 0
    4.   0   0   1 0
    5. p.x p.y p.z 1
    6.  
    If it only rotates, it will be:
    Code (csharp):
    1.  
    2. u.x u.y u.z 0
    3. v.x v.y v.z 0
    4. w.x w.y w.z 0
    5.  0   0   0  1
    6.  
    And if it only scales, it will be:
    Code (csharp):
    1.  
    2. sx 0  0  0
    3. 0  sy 0  0
    4. 0  0  sz 0
    5. 0  0  0  1
    6.  
    Where sx/sy/sz are scale factors for each axis.

    You also can do skew, and combine all transforms in one. Scale is length of each axis vector, rotation is determined by where the vectors are pointing and so on.

    That only works as long as it is not a projection matrix. Meaning there's distinct 0 0 0 1 pattern in the rightmost column (in row-major representation anyway)
     
  9. isawyou0

    isawyou0

    Joined:
    Oct 8, 2020
    Posts:
    30
    Vector3 Multiply(Vector3 a, Vector3 b)
    {
    return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
    }
    Vector3 Transform2( Vector3 vector, Quaternion rotation)
    {
    float x = rotation.x + rotation.x;
    float y = rotation.y + rotation.y;
    float z = rotation.z + rotation.z;
    float wx = rotation.w * x;
    float wy = rotation.w * y;
    float wz = rotation.w * z;
    float xx = rotation.x * x;
    float xy = rotation.x * y;
    float xz = rotation.x * z;
    float yy = rotation.y * y;
    float yz = rotation.y * z;
    float zz = rotation.z * z;

    return new Vector3(
    vector.x * (1.0f - yy - zz) + vector.y * (xy - wz) + vector.z * (xz + wy),
    vector.x * (xy + wz) + vector.y * (1.0f - xx - zz) + vector.z * (yz - wx),
    vector.x * (xz - wy) + vector.y * (yz + wx) + vector.z * (1.0f - xx - yy));
    }

    void WorldToLocal( Transform parentboss,Transform other, out Vector3 rp,out Quaternion rq, out Vector3 rs)
    {
    Vector3 invScale = parentboss.localScale;
    if (invScale.x != 0.0f)
    invScale.x = 1.0f / invScale.x;
    if (invScale.y != 0.0f)
    invScale.y = 1.0f / invScale.y;
    if (invScale.z != 0.0f)
    invScale.z = 1.0f / invScale.z;

    Quaternion invRotation = new Quaternion(-parentboss.rotation.x, -parentboss.rotation.y, -parentboss.rotation.z, parentboss.rotation.w);

    rq = (invRotation* other.rotation).normalized;
    rs= Multiply(other.localScale, invScale);
    Vector3 tmp = other.position - parentboss.position;
    rp=Transform2(tmp, invRotation);
    rp=Multiply(rp, invScale);
    }

    Vector3 tt;
    void OnDrawGizmos()
    {
    Transform p1=GameObject.Find("GameObject (1)").transform;
    Transform p2=GameObject.Find("GameObject (2)").transform;
    if (!tt.Equals(p1.position))
    {
    Vector3 rp;
    Quaternion rq;
    Vector3 rs;
    WorldToLocal(p1, p2, out rp, out rq, out rs);
    // LocalToWorld(p1, p2,out rp,out rq,out rs);
    p2.position = rp;
    p2.rotation = rq;
    p2.localScale = rs;
    tt = p1.position;
    }
    }

    not working it's killing me, it's been more than 30 hours now, the gameobject transform p2 become truly a child of p1 but behaves weirdly
     
  10. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,571
    Nope.
    "return rotation * vector"
    https://docs.unity3d.com/ScriptReference/Quaternion.html
    https://docs.unity3d.com/ScriptReference/Quaternion-operator_multiply.html

    Nope.

    Transform.worldToLocalMatrix
    https://docs.unity3d.com/ScriptReference/Transform-worldToLocalMatrix.html

    Additionally see:
    https://docs.unity3d.com/ScriptReference/Matrix4x4.html
    https://docs.unity3d.com/ScriptReference/Matrix4x4-rotation.html

    You could LITERALLY multiply other.localToWorldMatrix with parentboss.worldToLocalMatrix, then extract components. And you wouldn't even need to do that if other was parented to parentboss in the first place.

    And so on.

    Currently you're making your life more difficult by not reading documentation.