Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- The solution I'm currently using seems to be missing here.
- Assuming that the plane normal is normalized (`|Vn| == 1`), the signed angle is simply:
- For the right-handed rotation from Va to Vb:
- `atan2((Va x Vb) . Vn, Va . Vb)`
- For the left-handed rotation from Va to Vb:
- `atan2((Vb x Va) . Vn, Va . Vb)`
- which returns an angle in the range [-PI, +PI] (or whatever the available atan2 implementation returns).
- `.` and `x` are the dot and cross product respectively.
- No explicit branching and no division/vector length calculation is necessary.
- Explanation for why this works: let alpha be the direct angle between the vectors (0° to 180°) and beta the angle we are looking for (0° to 360°) with `beta == alpha` or `beta == 360° - alpha`
- (1) Va . Vb == |Va| * |Vb| * cos(alpha) (by definition)
- (2) == |Va| * |Vb| * cos(beta) (cos(alpha) == cos(-alpha) == cos(360° - alpha)
- (3) Va x Vb == |Va| * |Vb| * sin(alpha) * n1
- (by definition; n1 is a unit vector perpendicular to Va and Vb with
- orientation matching the right-hand rule)
- Therefore (again assuming Vn is normalized):
- (4) n1 . Vn == 1 when beta < 180
- (5) n1 . Vn == -1 when beta > 180
- So when beta < 180:
- (6) sin(alpha) * n1 . Vn == sin(alpha) == sin(beta)
- Otherwise:
- (7) sin(alpha) * n1 . Vn == -sin(alpha) == sin(beta)
- From (3), we have:
- (8) (Va x Vb) . Vn == |Va| * |Vb| * sin(alpha) * n1 . Vn
- And by plugging (6) and (7) into (8), we get:
- (9) (Va x Vb) . Vn == |Va| * |Vb| * sin(beta)
- Finally
- tan(beta) = sin(beta) / cos(beta) == ((Va x Vb) . Vn) / (Va . Vb)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement