camera3d
Mojo module 🡭
camera3d
The orthographic camera every 3D mark projects through: an elevation, an azimuth, and the map from a data-space point to a 2D position plus a depth (#345).
No drawing here, and nothing about any particular chart. A camera is a numerical question with a right answer – a known point at a known angle lands at a hand-computable position – so it is testable in isolation, which is why it is the first of #345’s five steps and why it is a leaf module with no package imports.
Why this lives here and not in canvas. It is pure geometry with
nothing chart-specific in it, which is usually the signal that a thing
belongs in the drawing library – that is the test #579 applies, and it
is how Path.arrow_head, Path.regular_polygon and Path.extend got
there. Put to canvas directly, the answer was a sharper test: does the
code encode something only canvas knows? BoundsTarget does – a
stroke’s box needs canvas’s outline maths, text’s needs its font
metrics. This does not. It is a 3x3 rotation and dropping an axis, and
any competent implementer writes the same thirty lines, so canvas would
own an API forever for a type it never calls and has no special
knowledge of.
Where canvas’s 3D interest really starts is where 3D meets
rasterisation: a fill_mesh taking per-face depths, or the polygon
splitting that would make the painter’s limitation below fixable rather
than documented. If #345 produces either, the camera goes upstream with
it as the thing that feeds it.
Orthographic, not perspective. Parallel lines stay parallel and a unit of data is the same size wherever it sits in the scene, which is what makes a 3D axis readable at all: under perspective the far end of an axis is shorter than the near end, so a tick spacing means two different things in one picture.
Depth is for ordering, not for measuring. project() returns a
z alongside the 2D position, and the only use for it is sorting what
to draw first: canvas is a painter’s-algorithm rasteriser with no
z-buffer, so a nearer surface hides a farther one purely by being drawn
second. That makes the ordering the whole of the correctness, and it
has a documented failure: two shapes that interpenetrate, or one long
thin shape crossing another, have no single right order and a
centroid-depth sort will pick a wrong one. Splitting the geometry or a
real z-buffer are the fixes, and canvas has neither. Saying so is
part of the contract; pretending otherwise is not.