Search Unity

Quaternion rotation around a custom point position ?

Discussion in 'Scripting' started by Dolmen007, May 21, 2013.

  1. Dolmen007

    Dolmen007

    Joined:
    Nov 25, 2012
    Posts:
    18
    Hi everyone,

    I'm actually scripting a little 3rd character controller.

    I'm working with a Logitech gamepad, and the left joystick is use to move the player (like in Assassin's Creed for example)
    (It works great for now :D) and the right joystick is normally use to move camera when player is not moving or to turn player (left/right) when he move but with camera follow behind the character. (Play AC and you will see :p)

    And my problem is really for the camera rotation.
    Because my camera is not directly parented to the character root (I use a camera follow script)
    when I want to rotate the camera, his rotating pivot is not where I want it to be.
    How can create a quaternion rotation with a custom point position for pivot ?
    Like build in solution "transform.RotateAround" but in quaternion.

    I don't know if it's possible, but I hope someone could help me.
    Thank you in advance.
     
  2. Dolmen007

    Dolmen007

    Joined:
    Nov 25, 2012
    Posts:
    18
    Good evening,

    I just found this in the UnityEngine.dll in the Transform class for RotateAround (Vector3, Vector3, float) : void
    But I don't really understand the last line.

    Code (csharp):
    1. using System;
    2. public void RotateAround (Vector3 point, Vector3 axis, float angle)
    3. {
    4.     Vector3 vector = this.position;
    5.     Quaternion rotation = Quaternion.AngleAxis (angle, axis);
    6.     Vector3 vector2 = vector - point;
    7.     vector2 = rotation * vector2;
    8.     vector = point + vector2;
    9.     this.position = vector;
    10.     this.RotateAround (axis, angle * 0.0174532924f);
    11. }
    12.  
    Why calling this at the past last line ?
    If someone can explain that to me, maybe I will transform that directly for my project.

    Code (csharp):
    1. using System;
    2. public void RotateAround (Vector3 axis, float angle)
    3. {
    4.     Transform.INTERNAL_CALL_RotateAround (this, ref axis, angle);
    5. }
     
  3. Dolmen007

    Dolmen007

    Joined:
    Nov 25, 2012
    Posts:
    18
    Nobody know how to move temporarily the pivot without creating an empty ?
     
  4. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    781
    That 0.0174532924f is one degree in radians. Still no idea why they they're rotating it an extra one degree at the end though.
     
  5. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,717
    It's (Angle * 0.017...)

    It's the quick way to convert degrees to radian.

    360 degrees * 0.017 = 2 * Pi
     
  6. Nition

    Nition

    Joined:
    Jul 4, 2012
    Posts:
    781
    Ah thanks, that makes some more sense at least.
     
  7. drudiverse

    drudiverse

    Joined:
    May 16, 2013
    Posts:
    218
    Dolmen, you are a genius for finding that function... for a start, rotateAround() function behavez bizarrely because when the angle goes over 180 the object flips and goes back to say 10 instead of 190, so i haven't seen where in that function that happens... i think that the rotate around point thing is just a case of substracting the object centre position which is default quaternion rotation from desired point rotation and translating it there, so only the first 3 lines. the other lines are weird. Also, the last line is RotateAround... so how can a function use itself in it's own definition, it is a kind of recursion...

    Someone understand that?!?

    indeed the other 3 lines with vector 2 should be ... rotation * this.transform.rotation... in order to multimply the quaternion matrices and add them, and not the 4 lines that follow int that function...

    you have to rotate by desired angle and then move to desired position. just by deleting 2 vector 3's.

    ... oh bugger. i wrote the function in 5 minutes and then i spent 55 minutes scratching my head about why it wasnt working... i had written the last line as object.transform.translate(bla) instead of transform position +=... the last line killed me. not programmed unity since 2013.

    rotation around for a point 0.5 underneath the game object... have to state the rotate point as relative to the rotated game object for this method:

    function qRotateAround(obj : GameObject, axis : Vector3, angle : float)
    {
    //point is not absolute point in space, it's relative to the gameobject
    var objDirection1 : Vector3 = -obj.transform.up.normalized*(obj.transform.localScale.y*0.5);
    var worldpoint1 = obj.transform.position + objDirection1 ;
    obj.transform.rotation *= Quaternion.AngleAxis (angle, axis);
    var worldpoint2 = obj.transform.position + (-obj.transform.up.normalized*(obj.transform.localScale.y*0.5)) ;
    var difference : Vector3 = worldpoint2 - worldpoint1;
    obj.transform.position -=difference;

    }
     
  8. deliriumz

    deliriumz

    Joined:
    Aug 22, 2012
    Posts:
    34
    drudiverse that is
    It flips around because the angle is always the smallest angle. Seeing as 180 is the largest angle you can make without knowing the sign, that's why you're getting results you're not expecting ( it should not flip to 10. in the example of expecting 190, it should go go back down to 170 ). If you want to know the angle in a single direction, you'll have to do some more calculations, as the sign requires a rotation axis.