Texture animation
Glide texture binding advances animated TEXBSI images on demand.
Each loaded image retains a current frame and a next-update deadline. The frame starts unset and the deadline starts at zero. Frames belonging to one image share this state wherever the image is drawn.
An automatic frame request selects frame zero for a single-frame image. For an animated image, it advances by one frame when the BIOS tick count has reached the deadline, or when the current frame is unset. Advancing past the final frame wraps to zero. The next deadline becomes the current tick count plus the image’s frame delay. The first automatic request therefore selects frame zero, even if its previous deadline lies in the future.
The delay comes from the TEXBSI header’s anim_delay: milliseconds multiplied
by 18.2 and divided by 1000, rounded to an integer tick count. A result of zero
becomes one tick. See the TEXBSI header.
A late request advances only once. It does not catch up through all frames whose durations elapsed. An image that is not bound does not advance merely because time passes. Repeated bindings before the next deadline retain the same frame.
An explicit frame request selects that frame and replaces the retained current frame without changing the deadline. A later automatic request continues from that selected frame. This state belongs to the loaded texture image, not to an individual mesh instance.
Loaded-image lifetime
The loaded-image cache identifies names with a six-digit base-40 key. Its digit
alphabet, in ascending order, is 0123456789abcdefghijklmnopqrstuvwxyz~_#%.
ASCII uppercase letters are converted to lowercase. Conversion stops at the
first null byte, period, character outside that alphabet, or after six
characters. Missing trailing digits are filled with %. The first character
is the most significant digit. Characters after the stopping point do not
distinguish cache entries, and the source bank path is not part of the key.
Looking up an already loaded image reuses its texture record and increments its reference count. It does not reset the current frame or animation deadline, and does not add the active resource group’s ownership bit.
Loading a TEXBSI bank visits every image record in the bank. For each already loaded image, it increments the reference count and adds the selected group’s ownership bit without resetting animation state. Newly decoded images receive the selected group’s ownership bit. Bank ownership therefore includes images that have not been requested by a model or terrain polygon. Repeated records increment references again while retaining the same ownership bit.
Images can belong to multiple resource groups. Releasing a group clears that group’s ownership bit and releases its reference. A record retained by another group keeps its animation state. When no ownership bits remain, group cleanup forces final release even if repeated lookups within that group increased the reference count. Final release frees every frame and clears the image record. A subsequently loaded image receives the initial frame and deadline state.
Book-menu setup saves the selected resource group and selects group 30 for menu loading. Menu cleanup restores the saved selection. Its release argument controls group release: zero retains group 30, and any nonzero value releases it. Closing the book menu requests release; preparing its contents first runs cleanup without release. Releasing menu ownership preserves an image’s animation state when another resource group still owns it.
The banks referenced by MENU.ROB, INVENTRY.ROB and the configured book-page
surfaces contain only single-frame texture images. Their image keys do not
match any animated image in the shipped TEXBSI banks. Shipped TEXBSI image
names consist of six ASCII letters or digits.
World-resource cleanup releases group 31 when world resources are loaded, then clears the loaded state. Repeating cleanup with that state already clear does not release the group again. World transitions perform this cleanup before loading the destination world’s resources.
Model polygon admission
The ordinary actor dispatcher requires both the runtime animation-update exclusion and object-update exclusion to be clear before preparing an actor’s model. Its hidden flag must also be clear before model submission. A static-model actor needs a loaded model. These actor gates precede polygon admission; hiding an actor or excluding it from drawing prevents its model from requesting texture frames.
With PVO disabled, the actor dispatcher’s static and animated PVO eligibility helpers both admit the actor. The pose-preparation helper returns success; it does not add a visibility rejection. The animation exclusions and hidden flag have separate update and presentation effects.
Before model polygons are prepared, draw submission classifies a bound around
the model origin transformed into scaled camera space. Let (x, y, z) be that
origin, r the model header radius in engine units, and (sx, sy) the
projection scales. Its depth interval is [z-r, z+r]; its
horizontal and vertical intervals are [x-hx, x+hx] and [y-hy, y+hy], where
hx = 1.415 * (r*sx) and hy = 1.415 * (r*sy). The decimal multiplier is
1.415. The scaled radii, multiplied side radii and interval endpoints are
stored in single precision.
Submission rejects a depth interval whose upper endpoint is at or before the
near plane, or whose lower endpoint is at or beyond the far plane. It rejects
a side interval whose upper endpoint is at or below -z, or whose lower
endpoint is at or above z. Otherwise it records each plane crossed by an
interval. An endpoint exactly on a plane does not count as crossing it.
No crossed planes selects the unclipped polygon preparation path; any crossed
plane selects the clipped path. A rejected bound does not enter the draw list.
Ordinary model drawing visits the authored polygons in order. A polygon passes its facing test only when the vector from the local-space camera position to its first authored vertex has a strictly negative dot product with the selected frame’s face normal. A zero result rejects the polygon. Both shaded and unshaded drawing use this test. Solid-color polygons do not bind a texture.
Queued-model draw flag 0x04 selects a separate explicit-frame path. This path
prepares only the model’s first polygon, bypasses the ordinary facing test and
uses the instance’s explicit texture-frame selection. Ordinary drawing requests
automatic frame selection. Shipped ROB segment attribute bytes use only
0x00, 0x02 and 0x40; none selects the explicit-frame path when copied
unchanged into the queued-model draw flags.
Both paths prepare a polygon before binding its texture. They bind only when preparation returns at least three vertices. Earlier object rejection still applies.
The clipped preparation path transforms vertices into camera space with the
horizontal and vertical projection scales already applied.
It classifies each vertex against the near and far depth planes and the four
side planes x = -z, x = z, y = -z, and y = z. Points exactly on a
plane are inside. A polygon whose vertices are all outside the same plane is
rejected immediately. Otherwise, clipping visits the near, far, left, right,
negative-Y and positive-Y planes in that order, as needed.
Preparation returns the remaining vertex count. It does not require projected area or covered pixels: coincident vertices can still satisfy the count check. The unclipped preparation path retains the input vertex count. Thus texture binding admission is distinct from both an object’s visibility bound and the eventual rasterized coverage.
Placed flat admission
Ordinary MPSF flats enter the same bounded draw queue as models, using their generated sprite bound and camera-facing transform. Their drawing flags select the first-polygon path described above, so they bypass the ordinary face-normal test. Their instance frame selection is automatic. After polygon preparation returns at least three vertices, they request a frame from the shared image timeline before drawing.
The generated bound radius uses the source image width and height before texture
scale. Form the single-precision squared diagonal width² + height², apply the
quantized square-root table, and halve that
result with a single-precision store. Multiply by the texture scale and the
submitted geometry scale, then store the radius as single precision. The
ordinary MPSF geometry scale is 1. The bound uses the same projection-scaled
sphere classification as queued models; it is not the exact Euclidean diagonal
of the final quad.
A flat rejected by its bound or polygon clipping does not request a frame. A flat that survives preparation can request a frame even if it covers no pixels. Using the first-polygon path does not make the request an explicit frame override when the instance selects automatic playback.
Terrain triangle admission
Terrain submits the cells in its camera window. Each cell tests its two triangles separately. The dot product of the vector from the camera to the cell’s anchor vertex with that triangle’s stored face normal must be strictly negative. A zero result rejects the triangle.
An admitted triangle copies its three prepared camera-space vertices and classifies them against the same six clipping planes used for model polygons. A common outside plane rejects it. Otherwise it clips as needed and requires at least three remaining vertices before binding the cell’s texture with an automatic frame request. The texture request precedes polygon drawing. Clipping boundaries are inclusive, and coincident vertices can still produce an automatic request. Rejected or back-facing terrain triangles do not advance their texture image.