Skip to content

Camera3D

Mojo struct 🡭

Camera3D

@memory_only
struct Camera3D

An orthographic view of a scene, given as an elevation and an azimuth in degrees.

elev is the angle above the x-y plane and azim the rotation about the z axis. The defaults, elev=30 and azim=-60, look down on the scene from one corner: enough elevation to separate the three axes, and an azimuth that leaves none of them pointing straight at the reader, where it would have no length to read.

The two rotations compose in one order and only one: azimuth about z first, then elevation about the rotated x. Doing it the other way round gives a different and wrong picture – the axes tilt out of plane – and the difference is invisible at elev=0, which is exactly the case a careless test would check.

Fields

  • elev (Float64)
  • azim (Float64)

Implemented traits

AnyType, Copyable, Deinitable, ImplicitlyCopyable, Movable

Methods

__init__

fn def __init__(out self, elev: Float64 = 30, azim: Float64 = -60)

Build a camera. The four trigonometric values are computed once here rather than per point: a surface3d projects every vertex of a grid through one camera, and sin/cos per vertex would be the whole cost of the projection.

Args:

  • elev (Float64): Degrees above the x-y plane.
  • azim (Float64): Degrees of rotation about the z axis.
  • self (Self)

Returns:

Self

project

fn def project(self, x: Float64, y: Float64, z: Float64) -> Projected

Project a data-space point to camera space.

Azimuth turns the scene about the z axis:

x' =  x cos(a) + y sin(a)
y' = -x sin(a) + y cos(a)

then elevation tips it about the rotated x axis, which leaves x' alone and mixes y' with z:

horizontal = x'
vertical   = -y' sin(e) + z cos(e)
depth      = -(y' cos(e) + z sin(e))

The minus sign on depth is the whole of the convention. The camera sits at large y' and large z – above the scene and on the near side of it – which is what vertical already says by putting large y' low on the page, where the near edge of an elevated view belongs. Distance from that camera therefore decreases as y' and z grow, so the raw combination is nearness and the negation is what makes larger mean farther.

At elev=0, azim=0 this degenerates to (x, z) with depth -y – a plain side-on view – which is the case a test can check against the 2D frame without trusting any of the trigonometry.

Args:

  • self (Self)
  • x (Float64): Data-space x.
  • y (Float64): Data-space y.
  • z (Float64): Data-space z.

Returns:

Projected: The 2D position and the depth sort key.