1

Background: I am creating an AR treasure hunt app. It is simple, it has a locator that tells you where the treasure is relative to you. I have the camera being the origin and the treasure being an object in AR world.

Question: I would like to rotate my arrow according to where in space the treasure is at. but in 2d. Basically, I would ignore the relative forward plane that is camera.forward.

Example: If the camera rotation is default, the angle can be calculated as atan2(dy,dx). If the camera is looking straight down, the angle is atan2(dz,dx).

What I have tried:

Quaternion lookRot = Quaternion.LookRotation(target.transform.position - origin.transform.position);
Quaternion relativeRot = Quaternion.Inverse(origin.transform.rotation) * lookRot;

Relative rotation is correct in 3d space but I would like to convert that into 2d ignoring the camera.forward plane. So even if the treasure is in front or behind the camera, it should not change the angle.

Byte
  • 2,920
  • 3
  • 33
  • 55
  • in 2D use `angle = atan2(y,x)` – MBo May 30 '18 at 17:46
  • @MBo The world itself is in 3d and the camera rotation changes over time. So I am not sure how do you derive x and y from it, since it is not always pointing straight into the z plane. – Byte May 30 '18 at 17:55
  • But you wrote about ignoring z. Just project point coordinates onto z=0 plane – MBo May 30 '18 at 17:58
  • @MBo Thank you, I updated the title. Sorry for the confusion – Byte May 30 '18 at 18:00
  • Now I don't understand the question. If you want to draw arrow in z=0 plane, then my comment is still valid. – MBo May 30 '18 at 18:08
  • @MBo When I used the word z-plane, I meant origin.forward. Which it could be the (0, 0, 1) that is the z plane. But it could be virtually anything else. My apology for the confusion. – Byte May 30 '18 at 18:15
  • 1
    Search swing twist decomposition – minorlogic May 31 '18 at 06:55
  • @minorlogic Woh, I think this might be it! Thank you for pointing that out – Byte Jun 01 '18 at 21:05

4 Answers4

3

enter image description here

Okay so I’m hoping this makes sense. You’re going to need some sort of if statement to determine if your character is looking along the x, y or z plane. Hopefully the diagram is clear as to what those parameters are but if not. To be looking in the “x” plane for example, the y rotation would have to be between 45° and -45° or 135° and -135° AND the z rotation would have to be between 45° and -45° or between 135° and -135°.

Essentially what you’ve got is a sphere split into six parts, two parts for each plane along which the character could look. Once you’ve determined which plane the character is looking in you can determine the direction by finding the difference in position between the character and the treasure along the two planes the character isn’t looking along. Then use trig to calculate the angle

Community
  • 1
  • 1
Tom Ryan
  • 397
  • 2
  • 6
  • 26
  • Thanks Tom, I think it might work. The angle may be less accurate and jumpy when transitioning from one plane to another. If by Monday I dont see a better answer, I will accept this and implement it. – Byte Jun 01 '18 at 20:56
2

Replying to an old thread, but I was struggling with the same problem and found a relatively simple solution:

Project the position of the target (relative to the origin) on a plane defined by the forward vector of the camera. Then just rotate towards the projected point:

Vector3 diff = target.transform.position - origin.transform.position;
Vector3 projected = Vector3.ProjectOnPlane(diff, Camera.main.transform.forward);
origin.transform.rotation = Quaternion.LookRotation(projected);
0

Calculate the difference in x and y coordinates simply by subtracting transform.x for one object by transform.x of another object and the same process for y coordinates and then use Mathf.atan(difference in y/difference in x) to calculate the angle. Then put the z rotation to this angle and assign the x and y rotation to what they already were.

Tom Ryan
  • 397
  • 2
  • 6
  • 26
  • Thanks Tom, I think my question is not worded very well, but the x and y calculation is not as straight forward as grabbing the difference. It would only work if the origin has not rotated. For example, if the origin is looking down 90 degrees. x and y is represented by x and z. y becomes irrelevant. – Byte May 30 '18 at 18:24
  • So in essence it’s a 2d environment but the plane on which it is 2d changes – Tom Ryan May 30 '18 at 18:25
  • That would be my question :) What is the correct approach/manipulation to produce the angle. – Byte May 30 '18 at 18:30
  • 1
    @byte if you understand basic trigonometry then you should be able to draw a diagram and try to figure out what you’re working with. If not I’ll give it a look when I get home – Tom Ryan May 30 '18 at 18:33
  • I think you’re just going to have if statements determining which plane you’re on and then have a different calculation in each case, the calculation I mentioned before – Tom Ryan May 30 '18 at 18:39
  • Thanks Tom. Would be great if I could use a couple of if/case unfortunately, the origin.forward is not discreet. It is a continuum in spherical rotation. – Byte May 30 '18 at 19:38
  • Can you not have an if statement with the condition being a range? – Tom Ryan May 30 '18 at 19:45
0

Turns out there is a very simple way to get relative X and Y of the target.

Vector2 ExtractRelativeXY(Transform origin, Transform target) {
    // Get the absolute look rotation from origin to target.
    Quaternion lookRot = Quaternion.LookRotation(target.transform.position - origin.transform.position);
    // Create a relative look rotation with respect to origin's forward.
    Quaternion relativeRot = Quaternion.Inverse(origin.transform.rotation) * lookRot;
    // Obtain Matrix 4x4 from the rotation.
    Matrix4x4 m = Matrix4x4.Rotate(relativeRot);
    // Get the 3rd column (which is the forward vector of the rotation).
    Vector4 mForward = m.GetColumn(2);
    // Simply extract the x and y.
    return new Vector2(mForward.x, mForward.y);
  }

Once obtained x and y, turn it into angle using angle = atan2(y,x) as suggested by both MBo and Tom.

This works because of the matrix components of the quaternion can be demonstrated in multiple vectors. Better illustration is found here https://stackoverflow.com/a/26724912.

Byte
  • 2,920
  • 3
  • 33
  • 55