Look rotation but using the up axis

So my problem is I want to create a rotation that has the specified up and forwards direction but prioritises the up axis.
Initially, I thought that Quaternion.LookRotation would be perfect but this aligns the forward axis and then the up and right axes are calculated from that using the cross-product and the upwards vector you provide. This means that the resultant up axis isn’t necessarily the same as the one you pass in…

How could I write a function that would do the reverse of this? So that the up axes are the same and the forward and right are calculated using the cross-product instead.

Thanks a lot!

Sounds like you just want to swap the input axes, supply the “up” vector as your look at and the “forward” vector as your up??

That would result in a rotation where the Up axis is equal to the Forward vector you pass in, which isn’t really what I want. All I wanted was a LookRotation where the up axis you get out is guaranteed to be the same as the up axis you pass in, at the expense of the forward axis. (the reason this wasn’t already the case was because the forward and up axes I was passing into LookRotation weren’t perpendicular)

I was able to find a fix by setting the forwards input equal to the cross product of the up and right axis before passing it into the LookRotation function, which just made sure that the inputs into the function were already perpendicular, but ensuring that the up axis is the same if that makes sense.

        var upwards = point.position.normalized;
        var forwards = Vector3.Cross(point.right, upwards);
    

        Quaternion rotation = Quaternion.LookRotation(forwards, upwards);

Could you be clearer.

what do you mean up has priority over forward?
Could you maybe draw a diagram

I understand the ask, and would also love if there was a builtin function that did this. If you want your, say, gun turret to aim towards a target but always stay locked to the surface it’s mounted on, this could be a 1-line facing if this method existed.

The first and easiest to follow method to do this is to point at the up direction with the actual target as the “hint”, and then flip it around. A slight improvement on this is to make the “up hint” the opposite direction as the target, as this involves a simple 90-degree down rotation to get it right.

Vector3 targetDelta = target.position - transform.position;
transform.rotation = Quaternion.LookRotation(currentUpNormal, -targetDelta;
transform.RotateAroundAxis(90f, transform.right); // maybe 90 should be negative, I forget

You can refine this into a more pure-math solution and put it into a utility script if you like, but this is the idea.

1 Like

Thanks for this code StarManta, it works! Here’s a general purpose implementation at the Quaternion level:

public static Quaternion LookRotationLockedUp(Vector3 forward, Vector3 up)
{
    var q = Quaternion.LookRotation(up, forward); // Purposefully inverted
    var right = Vector3.Cross(forward, up);
    q = Quaternion.AngleAxis(90f, right) * q;
    return q;
}