Rotation around center by grabbing and pulling

I need to create a way to rotate an object around its center by grabbing and pulling. It needs to work when facing in any direction whether you are behind the object or on a side of it.

I want it to work similar to this video, but with grabbing and pulling in the air (does not have to be in contact with the object, or it can it doesn’t matter to me).

Any ideas on how to script this, I don’t want to import any OVR assets that might interfere with the custom grabbing I have already created.

Thanks in advance!

I’m using the Oculus rift headset and the OVR API.

When the trigger is pressed, calculate the nearest point on the sphere around the object (by just finding the vector between the controller position and the center, and then normalizing). Also store the orientation of the object at that point in some handy Quaternion property.

Then on every frame while the trigger is down, again find the nearest point on the sphere. Now use Quaternion.FromToRotation to calculate the rotation between the original point and the new one. Finally, multiply that by the original (stored) orientation of the object to find the new rotation.

1 Like

Thanks! Worked flawlessly!

Heres my code in case anyone is interested. Feel free to clean it up if you see a better way to do things!

[Header("Controller")]
    public OVRInput.Button grabButton;
    public OVRInput.Button resetRotationButton;

    [Header("Robot")]
    public GameObject robot;

    [Header("Activation Settings")]
    public float activationDistance;

    private Quaternion currentRot;
    private Vector3 startPos;
    private bool offsetSet;

    private void Start()
    {
        offsetSet = false;
    }

    // Update is called once per frame
    void Update()
    {
        if (OVRInput.Get(grabButton) && IsCloseEnough())
            Rotate();
        else
            offsetSet = false;

        if (OVRInput.GetDown(resetRotationButton))
            robot.transform.eulerAngles = Vector3.zero;
    }

    void SetOffsets()
    {
        if (offsetSet)
            return;

        startPos = Vector3.Normalize(transform.position - robot.transform.position);
        currentRot = robot.transform.rotation;

        offsetSet = true;
    }

    void Rotate()
    {
        SetOffsets();

        Vector3 closestPoint = Vector3.Normalize(transform.position - robot.transform.position);
        robot.transform.rotation = Quaternion.FromToRotation(startPos, closestPoint) * currentRot;
    }

    bool IsCloseEnough()
    {
        if (Mathf.Abs(Vector3.Distance(transform.position, robot.transform.position)) < activationDistance)
            return true;

        return false;
    }
3 Likes

Hey thanks for this!
How do I use it only for y axis?

You could take the result of that Quaternion.FromToRotation call, and use Quaternion.FromEulerAngles to create a new quaternion from only the Y component of that.

Or, you could ditch the fancy quaternion stuff and just use Mathf.Atan2 to calculate the angle you need to rotate around the Y axis (giving it the X and Z differences between the old point and the new point).

Sorry I am still not able to freeze the x and z rotation from the above script. Can you please edit it?

Try replacing line 48 with:

var rot = Quaternion.FromToRotation(startPos, closestPoint);
rot = Quaternion.Euler(0, rot.eulerAngles.y, 0);
robot.transform.rotation = rot * currentRot;
1 Like

Perfect! Works really well. Thank you for this :slight_smile:

1 Like

Remove the “{” in line 20.

1 Like

I have a doubt, I need to rotate the object by grabbing it. Should I attach this script to the GameObject?

Attach this script to the object (plane, cube, etc. 3D model) for which the object should be rotated. The robot in this script means 3D model and the user rotates the robot in this context.

Hello, thanks for the reply. Could you please help me a bit more, I’m unable to rotate the object. Grab button and Reset rotation button should be set to which buttons of the controller?

6836108--795266--Capture.PNG