Gullie667
Gullie667

Reputation: 135

Transforming with Quaternions (Set a Parent->Child hierarchy to a goal orientation described from the child's POV.)

Here is the closest thing I can come up with but the position is not correct.... The parent's goal position is what I am trying to determine. Any help is appreciated!

Quaternion rotation = goal.rotation * Quaternion.Inverse(child.rotation) * parent.rotation;
parent.MoveRotation(rotation);
Vector3 position = goal.position + (Quaternion.Inverse(parent.rotation) * child.rotation) * (parent.position - child.position);
parent.MovePosition(position);

enter image description here

Upvotes: 1

Views: 482

Answers (1)

derHugo
derHugo

Reputation: 90813

If I understand your graphic correctly what you have is

  • a parent object
  • a child object which is arbitrary positioned and rotated relative to the parent

and what you are trying to achieve is

  • set the rotation and position of the parent in a way so that the child matches a certain given rotation and position

You are somewhat pretty close.

Ignoring the scale (assuming there is no scaling involved in the entire hierarchy until the parent object) basically you can simplified say

finalChildRotation = targetParentRotation * localDeltaRotation;
finalChildPosition = targetParentPosition + parentRotation * localDeltaPosition;

We already know

var finalChildRotation = goal.rotation;
var finalChildPosition = goal.position;

var localDeltaRotation = child.localRotation;
var localDeltaPosition = child.localPosition;

so you can resolve the rest in the order

// orientation as only one unknown -> basically simply rotate back the delta from the given goal rotation
var targetParentRotation =  finalChildRotation * Quaternion.Inverse(localDeltaRotation);
// Now that we have our final rotation you can easily calculate the position
var targetParentPosition = finalChildPosition - targetParentRotation * localDeltaPosition; 

Little demo

public class Example : MonoBehaviour
{
    public Transform goal;
    public Transform parent;
    public Transform child;

    [ContextMenu("Place")]
    public void Place()
    {
        var finalChildRotation = goal.rotation;
        var finalChildPosition = goal.position;

        var localDeltaRotation = child.localRotation;
        var localDeltaPosition = child.localPosition;

        var targetParentRotation = finalChildRotation * Quaternion.Inverse(localDeltaRotation);
        var targetParentPosition = finalChildPosition - targetParentRotation * localDeltaPosition;

        parent.rotation = targetParentRotation;
        parent.position = targetParentPosition;
    }
}

enter image description here


However, if there is also scaling in play this will probably get more complex!

Upvotes: 3

Related Questions