0

I want a determined angle in a local rotated axis system. Basically I want to achieve the angle in a plane of a determined rotated axis system. The best way to explain it is graphically.

Enter image description here

I can do that projecting the direction from origin to target in my plane, and then use Vector3.Angle(origin forward dir, Projected direction in plane).

Is there is a way to obtain this in a similar way like Quaternion.FromToRotation(from, to).eulerAngles; but, with the Euler angles, with respect to a coordinate system that is not the world's one, but the local rotated one (the one represented by the rotated plane in the picture above)?

So that the desired angle would be, for the rotation in the local y axis: Quaternion.FromToRotation(from, to).localEulerAngles.y, as the locan Euler angles would be (0, -desiredAngle, 0), based on this approach.

Or is there a more direct way than the way I achieved it?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rustyBucketBay
  • 4,320
  • 3
  • 17
  • 47
  • 1
    I would suggest you improve your question a bit, personally I am having a bit of a hard time understanding what you are asking exactly. If you know the angle and the vectors, what's the problem? – Ron Sep 30 '20 at 11:18
  • Thanks for your comment and suggestion. The question is a little bit hard to explain, I did my best. The question is that although I achieve my results, I was asking for a better or more direct approach. As the `Quaternion.FromToRotation(from, to).eulerAngles` already exist in unity, with the world's axis system as reference I am asking If there is another similar finction for other axis that are not the world ones, to get the angles to that rotated system (local one) instead of the world axis system. – rustyBucketBay Sep 30 '20 at 11:22
  • I explain the problem I had and how I solved it to show how in the way to the solution I stepped into the question I am asking. Hope that makes sense. Let me know anything that might not be clear. – rustyBucketBay Sep 30 '20 at 11:25
  • 1
    This is not tested but... If I understand everything right, I think you can use `Transform.InverseTransformPoint` to get local coordinates of target and use `Quaternion.FromToRotation` where **"from"** will be `target_direction_local` and **"to"** will be `target_direction_local` with `y=0` (_i think this create rotation from target to plane in local coordinate system_). Then use `Quaternion.eulerAngles` to get it local angles. Finally create new Quaterion with `Quaterinion.Euler` where `x` is your angle and `y, z` are angles from eulerAngles. – szczur0 Sep 30 '20 at 13:29
  • thanks a lot for taking the time to understand my question and for your comment. I am familiar with `Transform.InverseTransformPoin` so your suggestion makes sense to me. I will try that out asap an let you know if that works! – rustyBucketBay Sep 30 '20 at 13:45
  • I dont understand very well the `y=0`, but I will give it a thought – rustyBucketBay Sep 30 '20 at 13:48
  • What is a *"locan Euler angle"*? – Peter Mortensen Sep 30 '20 at 17:36
  • Quaternion.FromToRotation(from, to).eulerAngles gives you the equivalent rotation in eulerAngles respect the world axis sytem. In mi picture, if you check the rotated axis sytem, that is the origin object local one, I want the desired rotation restpect the local axis sytem, so I my question asks if there could be a function that provided the eulerAngles respect that local axis system instead of the world axis system. – rustyBucketBay Sep 30 '20 at 18:06

1 Answers1

1

If I understand you correct there are probably many possible ways to go.

I think you could e.g. use Quaternion.ToAngleAxis which returns an Angle and the axis aroun and which was rotated. This axis you can then convert into the local space of your object

public Vector3 GetLocalEulerAngles(Transform obj, Vector3 vector)
{
    // As you had it already, still in worldspace
    var rotation = Quaternion.FromToRotation(obj.forward, vector);
    rotation.ToAngleAxis(out var angle, out var axis);

    // Now convert the axis from currently world space into the local space
    // Afaik localAxis should already be normalized
    var localAxis = obj.InverseTransformDirection(axis);

    // Or make it float and only return the angle if you don't need the rest anyway
    return localAxis * angle;
}

As alternative as mentioned I guess yes, you could also simply convert the other vector into local space first, then Quaternion.FromToRotation should already be in local space

public Vector3 GetLocalEulerAngles(Transform obj, Vector3 vector)
{
    var localVector = obj.InverseTransformDirection(vector);

    // Now this already is a rotation in local space
    var rotation = Quaternion.FromToRotation(Vector3.forward, localVector);
    
    return rotation.eulerAngles;
}
derHugo
  • 83,094
  • 9
  • 75
  • 115
  • Thanks a lot for your answer. I will try it out and let you know!! – rustyBucketBay Oct 01 '20 at 17:44
  • You nailed it. Both examples work. Thank you very much for taking the time to undesrtand the question and providing 2 approaches. Although I knew how to do it, these two way are much more simple and my understanding of rotations improves. – rustyBucketBay Oct 07 '20 at 20:34
  • However I dont understand why in the second example `var rotation = Quaternion.FromToRotation(Vector3.forward, localVector);`is a rotation in local space, as localVector is in the local space, but `Vector3.forward` is the world's forward. it works with `Vector3.forward`and gives the angle I am after, but I would say that there `obj.forward` would make more sense or at least I would have tried `obj.forward` before `Vector3.forward`. Do you understand my point? – rustyBucketBay Oct 07 '20 at 20:49
  • 1
    Oh I got it. Both vectors have to be in the same space. World's.forward in the local space its not (0,0,1), the same as obj.forward is not 0,0,1 in the worlds space, but the decomposition in worlds axis. So in local space Vector3.forward = 0,0,1 is the vector I need to depart from to reach the desired angle. Actually I introduced the obj.forwar and the vector both in world's space, and it works also, as expected. This is so amazing! thanks a lot! – rustyBucketBay Oct 07 '20 at 21:22
  • 1
    @rustyBucketBay yes you got it already!;) I like in particular that this also helped you to understand it yourself. That is what this page is (should be) mainly about in my eyes - to help you understand instead of only provide a ready to use code snippet. So very glad to help! – derHugo Oct 08 '20 at 07:46