The bake side of a tangent patch. A sphere_tex window is a finer map laid
over a patch of the sphere. To fill that map, a baker needs the frame the
primitive reads the patch in, and the direction each texel's centre faces.
A window has a centre c on the sphere and an along direction e1, both
in the object frame. It has half-extents a, b in the tangent plane. The
primitive derives the frame from c and e1 and reads the patch
gnomonically in it. A map baked in any other frame comes out mirrored,
turned or shifted, and only a flight over it shows the error. So frame
repeats the C's operations in the C's order, and dir gives texel
(i, j)'s centre in that frame:
s = -a + (i - 1/2) * 2a/w, t = -b + (j - 1/2) * 2b/h
n = (c + s*e1 + t*e2) / |c + s*e1 + t*e2|
i, j count from 1, as pixel does: (1, 1) is the first column along
e1 and the first row along e2. The formula is linear in i and j,
so a half-integer names a texel's edge.
A window's map is a ring. With an origin ox, oy, the window covers
columns ox .. ox + w - 1 and rows oy .. oy + h - 1 of the patch's grid.
Grid texel (I, J) lives at canvas texel ((I mod w) + 1, (J mod h) + 1).
The baker samples it at dir(f, a, b, w, h, I + 1, J + 1). A map
scrolled by moving the origin and baking the new band holds the same bytes
as a fresh bake at the new origin. The primitive reads the window at plane
offset s0 = ox * (2a/w), t0 = oy * (2b/h). dir uses the same
product for its texel width.
The arithmetic is + - * / and the square root alone. So a bake gives
the same bytes on every machine, as the primitive does.
| Name | Signature |
|---|---|
| frame | frame(c, e1) -> frame |
| dir | dir(frame, a, b, w, h, i, j) -> x, y, z |
frame(
c,e1) ->frame
The orthonormal frame the primitive reads a patch in
c is the patch's centre and e1 its along direction, in the object
frame: +y the pole, +x the zero meridian. Each is {x, y, z} or
{x=, y=, z=}, and need not be unit length.
Returns { c = {x, y, z}, e1 = {x, y, z}, e2 = {x, y, z} }: c
normalised; e1 with its component along c removed, normalised; and
e2 = c × e1. Map columns run along e1, rows along e2. frame.c and
frame.e1 can go into a window entry as they are.
Returns nil for a zero-length centre, an along within a microradian of the centre or its opposite, or a non-finite component. The primitive refuses such a window too.
dir(
frame,a,b,w,h,i,j) ->x,y,z
The unit normal at the centre of texel (i, j) of a w x h map over a patch
frame comes from frame. a, b are the patch's half-extents: the
tangent of the half-angle each side subtends at the centre. w, h are the
map's size in texels. i, j are the texel, counted from 1.
Returns the unit normal in the object frame at
s = -a + (i - 1/2) * 2a/w, t = -b + (j - 1/2) * 2b/h. i, j can lie
outside the map: a half-integer names a texel's edge, and 0.5 the
patch's own edge.
Returns nil when:
a or b is not above 0;a² + b² > 1, a corner past 45 degrees;