Search Unity

Issues converting Quaternion to local space without using transform.localRotation

Discussion in 'Scripting' started by Barachiel, Aug 3, 2015.

  1. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    Hi all.

    I've been having a bit of trouble with this one and I've searched around for quite a while without much success.
    I need a Quaternion variable changed into local angles, but I can't use transform.localRotation or transform.localEulerAngles because I'm not setting the transform at this point, this is just one part of something else that is used to calculate the final result.

    This is the snippet of code in question:

    Code (CSharp):
    1. Vector3 CalculatePosition(float rotX, float rotY, float currentDistance)
    2.     {
    3.         Vector3 direction = new Vector3(0,0,-currentDistance);
    4.         Quaternion rotation = Quaternion.Euler(rotX,rotY,0);
    5.         return TargetLookAt.position + rotation * direction;
    6.     }
    This function is to calculate the position this object (usually a camera, but not always) should be at next.
    TargetLookAt is just an empty object used to keep track of something's position.
    Variables rotX and rotY are floats generated from the mouse x and y axis.
    If everything always aligned with world up this wouldn't be a problem, but since the object we're tracking isn't so limited, I need the Quaternion rotation to be local.

    I tried something like this:
    Code (CSharp):
    1. Vector3 CalculatePosition(float rotX, float rotY, float currentDistance)
    2.     {
    3.         Vector3 direction = new Vector3(0,0,-currentDistance);
    4.         Vector3 rot = transform.TransformDirection(rotX, rotY, 0);
    5.         Quaternion rotation = Quaternion.Euler(rot.x,rot.y,0);
    6.         return TargetLookAt.position + rotation * direction;
    7.     }
    While this does adjust the rotation correctly, something goes horribly awry in the conversion and when rotated around the target a certain amount, it completely flips out and starts going all over the place.

    As always, thanks for any help or insight you might offer. =)
     
  2. sz-Bit-Barons

    sz-Bit-Barons

    Joined:
    Nov 12, 2013
    Posts:
    150
    Hmm, I don't really understand your usecase. So I cannot answer properly.

    I wonder for what you need the rotation... maybe a direction vector would be enough for the things you do?
    Also it looks like you would need a two dimensional rotation. maybe it is is easier to work with one float as angle and sin, cos and atan2?

    Please describe more about what you wanna achieve and why... Right now I am unsure what you are trying to do.
     
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    Well considering that Transform.TransformDirection is for vectors that define direction, rather than rotation, it's not going to transform your rotations very well.

    And even if it did, because you're bring values from world space to local space, you would have wanted to use one of the 'InverseTransform...' methods.

    If you want to do that, you'll need to multiply the rotation by the inverse of the transform whose local space you want the rotation in:

    Code (csharp):
    1.  
    2.         public static Quaternion InverseTransformRotation(this Transform t, Quaternion rot)
    3.         {
    4.             return rot * Quaternion.Inverse(t.rotation);
    5.         }
    6.  
    Of course, I'm not certain this is what you actually need. From your code I don't know what you EXPECT to happen, versus what is actually happening.

    What is it you're attempting to accomplish?
     
    Kokowolo likes this.
  4. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    Sorry for the rather late reply, rather hectic going ons here and I expected to have more time on my hands.

    In regards to what I'm trying to accomplish, while this script will be reused for a few things the most obvious and pertinent use of it would be for a camera.

    In this case, a camera that can orbit a target and zoom in and out.
    To do this, I use GetAxis for the scrollwheel, as well as MouseX and MouseY.
    I calculate a float using the scrollwheel input and use it to determine a distance for smoothly zooming in and out, the result of which can be seen on line 3 above.
    MouseX and MouseY are fed into the Quaternion on the 4th line of my snippet on the first post.
    The final calculation returns a Vector3 so that I can tell the camera where it should be and the direction it should be facing.

    This all works fine.
    The issue is when I want the target to change orientation, and the camera to follow suit.
    In this case, an example of changing the gravity would be the best example.
    If the gravity changes so that the wall on the left is now the floor, with the character rotating and falling towards it, the camera cannot also rotate in that manner.

    This is why I was looking for some way to get a local quaternion, rather than a global one. The point at which I need the information is not the same point that the information is used, so transform.localRotation and the like can't be used in this case.

    Thanks for the help so far. =)