Aligning vector by rotation around non-orthogonal axis

64 Views Asked by At

To give a heads up at the start, I'm not too well versed in mathematical symbols and nomenclature. I'm probably in way over my head, but I'm giving it an attempt anyway. I'll be very thankful for any help you can give, but if you can give an answer in the form of code or pseudo-code, I'll be much more likely to understand it. If you give me just formulas, there's a chance you'll have answered correctly, but I might not be able to understand the answer to mark it as such. I will definitely try, though.

My background is programming, and the application today is a video game. I'm cross posting with the gamedev stack exchange, but this question seems much more mathematical in nature.

Outline

I have a specific object in my game, which I am trying to get into a certain orientation, using only a rotation around a specific axis. I am endeavoring to come up with a formula (implemented in code), which can calculate how many degrees of rotation around that axis will put the object into the desired orientation.

The Object

Model reference image

We have, basically, a rectangle. The four cubes on the end are to emphasize the corners visually. This all moves as one rigid object. This object has two axes running through it, shown as yellow and blue respectively (you may need to expand the image to see the lines, because they're thin). Each axis passes through two of the corners, and they intersect in the center of the object.

The Goal

The goal is to move one of these axes into a desired position, solely by rotating the object around the other axis. This is complicated by two factors:

  1. The two axes are not orthogonal.
  2. The desired position of one axis is not relative to the other axis, but to something external (the horizon).

For the purpose of this question, the yellow axis will be the one we're trying to get into position, and the blue axis will be the one around which the object rotates.

The "Desired Position"

The "desired position" of the yellow axis is an angle relative to the horizon. It's not a specific location, just an angle relative to the horizon. But it's specifically relative to where the horizon plane intersects with the plane of the axis being aligned. In case that sounds confusing (it does to me), here's another image to help:

Yellow axis plane

The yellow disc here shows the area that the yellow axis would rotate through if it were rotated around an orthogonal axis. The black line, marked with 0, shows the spot in that arc where the yellow axis would be level (even with the horizon). That's the line that the angle is measured relative to. The white arc and the white number show the current angle relative to that line.

Here is the code I use to calculate these vectors and the angle:

float GetAngleForPair(Vector3 axisFrontPoint, Vector3 objectCenterPoint, Vector3 objectUpDirection)
{
    var v = axisFrontPoint - objectCenterPoint;
    var side = Vector3.Cross(v, objectUpDirection);
    var flat = Vector3.Cross(Vector3.up, side);
    return Vector3.Angle(v, flat) * Mathf.Sign(v.y);
}

The Rotaton

Here's what rotating around the blue axis looks like: Rotation

The two corners that the blue axis pass through stay in place, while the other corners move. You'll notice the black target line also moves. This is because is it relative to the yellow axis, and just like the yellow axis, it isn't orthogonal to the blue axis. It moves to stay within the arc of the yellow axis, while keeping at horizon level.

The Question

The question itself is somewhat simple if you can wrap your head around the above. Given a target angle for yellow, how many degrees around the blue axis do I need to rotate the object in order to achieve that angle?

My Attempts (and the data I've gathered)

I've done a few simulations and graphed the results to try and understand the relationship between rotations about the blue axis, and their result on the yellow axis.

Here is an example test:

Rotation test from -90 to 90 degreses

Starting from yellow axis position -90, I rotate around the blue axis in .1 degree increments, until the yellow axis position reaches 90. I ran this simulation a number of times, with the object in different starting positions. Here's the data I got:

Rotation test result graphs

The horizontal axis shows the amount rotation around the blue axis in degrees. The solid lines show the angle of the yellow axis, relative to the black horizon line, as the object rotates. The dashed lines show the rate of change of the yellow axis' angle (the little spikes are calculation errors from when the angle crosses 0).

The red series show the results for the specific test shown in the video above, where the blue axis is flat with the horizon. In further tests, I rotated the object to give the blue axis its own offset angle from the horizon, like so:

Starting point for additional test

The angle of the blue axis seems to be the only other variable in this problem, because no matter how many different ways I rotated the object, as long as the angle of the blue axis relative to the horizon was the same, it produced the same results.

In total, it seems these are the only variables for this problem:

  1. The current angle of the yellow axis relative to where the horizon intersects with its plane.
  2. The target angle for the yellow axis, measured relative to the same.
  3. The angle of the blue axis relative to the horizon (or, in other terms, the difference in height between one corner of the blue vector and the center point of the object).

Closing

With all that said, I still don't know how to go about actually solving this problem. I don't know how to mathematically express the relation between these graphs.

If you took the time to read this enormous question, thank you. If you're going to attempt to answer it, I'll remind you again that any kind of pseudo-code would be well appreciated, but I'll do my best to work through any equations if you provide them. If you can provide me with better terms to describe the question, I will try to understand those as well and edit the question to make it more understandable.

Thank you again for your time.