# 用代码画人体解剖

> 先结构，后笔触：`butterfly/alive/anatomy.ts` 用在翅膀上的规则，用到一个人身上。从轮廓画出来的人，是人的路标图标。用骨架、体块和一台摄像机搭出来的人，能白白得到透视缩短、遮挡、接触和平衡，而且每一项都能检查。代码：`engine/src/canvas-core/character/human/`。

**伤疤。** 我们造的第一个人体模型，两条手臂悬在一个盒子形躯干旁边的空隙里：一个木偶。它的手是耙子，拇指像一根棍子一样从手腕伸出来，捏合永远合不上，一个九岁孩子的小腿短了 16%，还有一个 37 度的踝关节弯曲和一个 46 度的髋关节，混进了我们「凭眼睛调」的姿势里。下面的检查抓住了后四个。眼睛抓住了前三个。两样你都需要。

## 流水线

| 层 | 文件 | 它负责什么 |
|---|---|---|
| 比例法则 | `canon.ts` | 按比例法则表的每一**行**给出以头长为单位的标志点高度（成人 7.5；绘本孩子声明为 5.2，叠在真实的 6.2 之上）；分年龄的头身比表和分年龄的眼线高度表 |
| 骨架 | `skeleton.ts` | 由比例法则得出的骨骼长度；正向运动学；关节限位和锥形范围；**超出范围的姿势在加载时就抛错** |
| 人体模型 | `mannequin.ts` | 蛋形的胸廓、碗形的骨盆、肩带，四肢是带肌肉剖面的椭球链 |
| 头部 | `head.ts` | Loomis 球体 + 下颌；五官放**在**脸的曲面上；十一个表情参数 |
| 手 | `hands.ts` | 5 根手指，14 节指骨，指关节弧线，从手腕出发、带大鱼际肌块的拇指，姿势库，解算出来的捏合 |
| 平衡、够取 | `balance.ts` | 质心（Winter 体段质量）落在支撑多边形之内；解析式腿部 IK；数值解算的够取；对立式平衡（contrapposto） |
| 行走 | `walk.ts` | 由脚步生成的行走：足跟、踝、前足三个滚动支点，摆动弧线，骨盆起伏与反向旋转 |
| 服装 | `clothing.ts` | 衣物是充气后裁到合适长度的身体团块；它们随身体转动和摆动 |

一个身体部位是若干凸多边形的**并集**（一条肢体就是它的团块链两两扫掠而成），通过一台有真实焦距的针孔摄像机投影。轮廓是所有不在兄弟多边形内部的边界点，再减去部位从它的父部位长出来处的接缝：所以肘部没有接缝，但一条与自己上臂交叉的前臂仍然有它的遮挡线。

**人体模型是检查器，不是外观（进行中）。** 把这些体块按字面渲染出来，读起来就是一个人体模型。绘制层（`character/design.ts`）把骨骼绑定（rig）保留为姿势来源和检查器，并在它上面画出设计过的扫掠形：一条穿过各关节的动势线、一张手工设定的截面表、垂直于这条曲线的剪影。Mira 的服装和面包师 Theo（`characters/theo/baker.ts`，彩色铅笔）用了它。仍未解决的：袖山和前臂看起来像管子，从接触点出发的衣物垂坠只做了一部分，解剖标志点还没有在绘制层上表现为轮廓的转折。

## 比例法则（经过检查，而不是断言）

- 按年龄的头身比（Loomis）：1 岁 4，3 岁 5，6 岁 5.75，8 岁 6，9 岁 6.2，12 岁 7，成人 7.5，英雄式 8。
- 眼线：成人在头部的一半，孩子更低（九岁 0.44，一岁 0.38）。
- 成人：裆部在身高的一半，肘在腰线，腕在裆部，手 = 脸，脚 = 前臂。
- 每一种比例法则：肢体各段占（身体）高度的比例，取自 Winter 的人体测量表：上臂 18.6%，前臂 14.6%，手 10.8%，大腿 24.5%，小腿 24.6%，脚 15.2%，误差在 16% 以内。
- 风格化的比例法则是一个声明出来的行。绘本孩子把头放大 1.19 倍，并拿她这个身高的一个真实 6.2 头身孩子应有的身体高度来衡量。

## 关节

活动范围（AAOS / Norkin & White，取整）：肘 0-150，膝 0-140，髋屈曲 -20..125，但膝伸直时只有 95（腘绳肌），踝 -45..25，颈部总旋转 80，手指 MCP -20..90、PIP 0..110、DIP -5..80。腕、颈和肩是**锥体**（组合运动的一个椭圆），不是方框。任何解算姿势的东西（腿部 IK、够取、行走）要么待在范围之内，要么抛错；踝到了极限就抬起脚跟，而不是继续往下折，真实的脚跟就是这样做的。

## 手，已知的弱项

- 指关节排成一道**弧**（中指离手腕最远，小指远远退在后面）；手指长度顺序为中指 > 无名指 >= 食指 > 小指；指蹼皮肤在手指往上三分之一的地方。
- 拇指的掌骨埋在大鱼际隆起里：看得见的拇指从它的 MCP 关节处离开手掌，而不是从手腕。静止时它贴着食指，指向下方和前方。
- 接触是**解算**出来的，绝不是手填的：捏合把拇指指腹拉到食指指腹上；握持把每一个手指关节都拉到它所握的圆柱面上（没有一个陷进去）；挥手时前臂转动，直到掌心朝向镜头。
- 指甲长在远节指骨的背面，只在这一面转向摄像机时才画。

## 照着参考搭姿势，像老师那样搭

说出你打开了哪份参考（文件里引用了 Loomis、Hogarth、Williams、Perry 与 Burnfield）。先放脚，解算双腿，把质心送到支撑面上方，再把每只手送向一个目标。对立式平衡：承重脚靠近中线，骨盆在自由侧下沉，双肩朝相反方向倾斜。踮脚：脚趾弯折、平贴地面，质量移到前脚掌上方。坐姿人物的支撑面包括座位。

## 必须亲眼看的清单（没有任何检查能证明这些）

渲染人物设定页，按全尺寸看，找这些问题：手臂悬在空隙里（缺了肩带）；耙子手；从手腕伸出的拇指；脸转了、远侧那只眼睛却没有变窄；手挡住了脸；捏合没碰上；脚浮着或陷下去；外套像一个盘子一样搁在大腿上；伸出的手指看不出在指着什么。这里每一个问题都在我们人物设定页的某一稿里出现过，而且只靠眼睛才抓住。

## 闸门

`node tools/character-check.mjs` ：比例法则的比率、姿势库里每一个姿势的限位、骨骼长度恒定、左右对称、五根手指按长度排序且指关节成弧、捏合接触、平衡、脚踩在地面上（而不是穿过地面）、每个视图的身份一致、每种手笔的调色板色相族，以及对影片而言的脚步钉地（每帧滑动不超过 4 mm）。然后是它的反面双胞胎，每一个都必须失败：肘 170、膝反折、腕超出它的锥体、直腿踢、手指向后反弯、猫头鹰脖子、一个正在倾倒的人物、一件蓝外套、缺了眼镜。
