♥ lp-engine

Chapter 5

The heroines

Manaka Takane, Rinko Kobayakawa and Nene Anegasaki are the reason the game exists, and the most carefully built thing in it. Each is assembled from parts every time she appears, posed by a system that works on bone names, and given her face by swapping textures.

Built from parts

A heroine isn't one model. She's put together from up to eleven pieces, each its own small 3D model with its own textures:

partnotes
hairone model per hairstyle; it also carries the joints the faces follow
body, left arm, right arm, waist, legthe outfit: changing clothes swaps these
face (close) and face (far)two faces, chosen by distance (below)
left hand, right handshared base hands
accessorya prop, carried along on her head bone

What she's wearing is a wardrobe label: a record naming an archive entry and a motion class. The game turns it into the file for each part with fixed offsets (hair and body at +1, the arms at +3 and +4, the waist at +6, the leg at +8). Clothes, hair and accessories mix and match because every part is its own model.

Posed by name

Motions are stored per part too. A motion is a set of tracks named after the parts (_body, _larm, _hair and so on), and each part plays its own track on its own skeleton. Joints are matched by name, which is what lets one motion drive any outfit.

The pieces then have to agree where they meet. The hands copy the end joints of the arms, the waist copies joints from the leg, and both faces ride on the hair's joints. Seventeen named bones are also read back every update by Model_ApplyNamedBoneMtx, so the game knows where her head and hands are.

Script command 0x0F (chapter 3) switches her to one of 974 motions, blending into it over a few updates. Manaka has several times as many as Rinko or Nene.

A face made of textures

Her expressions aren't animated geometry. Each face model has four materials, eye, brow, cheek and mouth, and the game simply swaps their textures:

materialtextureschosen by
eye23mood, plus blinking
brow6mood
cheek2mood (a blush)
mouth12mood, or the lip-sync while she talks

A mood is one of 45 expressions a script can ask for (command 0x34). Two tables built into the game's code turn a mood, the current lip-sync shape and the blink state into the four texture numbers. Blinking runs on its own, and setting a new mood reloads her eye textures.

Close and far

There are two faces because the DS's screen is small. Model_ClassifyIdRangeToVariant uses the far face when her head is at least 210 units from the camera, and the detailed face for close-up camera angles. Each update, Model_UpdateCharaScene works out the distance again.

Speaking

Every voiced line is a clip in one big voice bank (chapter 8). Lip-sync works from two sources at once:

VoiceQueue_UpdateMode combines the two. The voice starts four scene updates after the script asks for it, and when the clip is over the mouth returns to its resting shape.

Light and outline

The heroines are toon-shaded: the DS's 3D hardware looks up a 32-step colour ramp from the lighting instead of shading smoothly. The game ships a ramp for each time of day, so she's lit differently in the evening than at noon. Outlines come from the hardware's edge marking, which draws an edge wherever two different polygon IDs meet. The game sets each material's ID by name (eyes, brows, face, hair) so the outlines land where an illustrator would draw them. Edge colours come from the base model, the outfit and the hair, each owning part of the table.

When she looks straight at the camera (within 15 degrees, Char_IsFacingTarget), the game switches to a different set of polygon IDs and edge colours, which changes where the outlines fall on her face.

The camera

Scenes don't move the camera freely. They pick from 150 presets (command 0x06), each a fixed position, target and lighting angle stored in three small files. The game builds a perspective view from the preset and lights her with two lights turned by the preset's angles.

How we know

We recorded a scene with Nene in the school break room, including every 3D command the game sent to the hardware. Then a generator rebuilt those commands from scene facts alone (heroine, outfit labels, accessory, time of day, camera preset, motion, mood, lip-sync shape and the number of updates since the motion began), reading only the game's own files and tables. At two different moments of that scene it produced every one of the 26,216 command packets the game sent, exactly. In lp-engine the game's own code poses and draws her, on the engine's reimplementation of the 3D hardware; the generator is how we know the rules, and how the engine's output was checked.

Still open. A few pieces of the costume data are only partly read, such as some shading-table variants and colour palettes. The full rule set, with the evidence for each rule, is in docs/RENDER_PRIMITIVES.md.