Direction vector: Correctly scale sin(radians(x)) + cos(radians(z)) with y axis

Question:

I have an issue with the directional transform math for a voxel raytracer I’m working on in Python. X axis is left-right, Y axis is up-down, Z axis is forward-backward: I calculate view direction from a camera angle stored in degrees, direction being the virtual arrow the point of view points toward: Z rotation translates to X and Z directions, Y rotation to Y direction, X rotation is ignored as I didn’t implement camera rolling. The conversion is done by running the rotation radians through a sine / cosine, for example: Rotation x = 0, y = 90, z = 45 becomes direction x = 0.7071067811865475, y = 1.0, z = 0.7071067811865475 since a 45* angle for rot Z means dir X and Z equally point toward that direction. A simple demo to visualize what I’m doing.

angle_y = 90
for angle_z in (0, 45, 90, 135, 180, 225, 270, 315, 360):
    dir_x = math.sin(math.radians(angle_z))
    dir_y = math.sin(math.radians(angle_y))
    dir_z = math.cos(math.radians(angle_z))
    print("x: " + str(dir_x) + " y: " + str(dir_y) + " z: " + str(dir_z))

Directions X and Z work as intended and form a perfect arch at every rotation as angle_z goes from 0* to 360*. The issue is the Y direction: If you’re looking straight ahead and it has a value of 0 everything works fine. But as you look up and down, the Y direction needs to correctly shrink the magnitude of X and Z with its intensity, otherwise extra "force" is added to the total direction which should never exceed X + Z as defined by their sin + cos. Therefore the following is wrong:

return dir_x, dir_y, dir_z

I tried the simplest solution which is a lot more accurate:

return dir_x * (1 - abs(dir_y)), dir_y, dir_z * (1 - abs(dir_y))

But this too causes incorrect perspective: As I look up or down it looks like the world shrinks vertically. I get an even more correct result by dividing dir_y by two:

return dir_x * (1 - abs(dir_y) / 2), dir_y, dir_z * (1 - abs(dir_y) / 2)

This stops the world from bending at first, but as you look closer to a full -90 / +90 angle up or down it makes everything bend like a concave mirror. What is the correct way to shrink X and Z with by the intensity of Y to get a direction arrow that correctly maintains magnitude?

Asked By: MirceaKitsune

||

Answers:

As proposed in comment, use spherical polar coordinates with your angles.

But as you look up and down, the Y direction needs to correctly shrink the magnitude of X and Z with its intensity

In your words you "shrink" your X and Z values by cos(angle_y)

dir_x = math.sin(math.radians(angle_z)) * math.cos(math.radians(angle_y))
dir_y = math.sin(math.radians(angle_y))
dir_z = math.cos(math.radians(angle_z)) * math.cos(math.radians(angle_y))

Using sin^2 + cos^2 = 1 you can check it’s always a unit vector

Answered By: Scout
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.