• 简体中文
  • 形状推导

    形状生成器返回点。其余一切都从这些点量出来。

    归一化

    轮廓被缩放到较长轴为 228.44 单位,并重新居中到形状空间的中心。生成器因此只需要把比例做对,而不需要绝对尺寸——这就是每个生成器里的参数读起来像圆整数字、而不是调过的常量的原因。

    跨度表

    对 160 个均匀分布的垂直位置,渲染器记录轮廓最左和最右的交点。查询在行之间插值。

    这就是眼睛待在身体里的原因。眼睛的锚点被夹在它所在高度的跨度内,即使凝视漂移把它往旁边推,脸也不会逃出狭窄的剪影。

    heightleftrightwidth
    15%90.4138.648.2
    30%61.2167.8106.7
    50%29.9199.1169.3
    70%21.2207.8186.7
    90%45.1183.9138.9
    import { getShape, SHAPE_IDS } from '@aora-bot/react';
    
    export default function Demo() {
      const shape = getShape('drop');
      const rows = [0.15, 0.3, 0.5, 0.7, 0.9];
      return (
        <table>
          <thead>
            <tr>
              <th>height</th>
              <th>left</th>
              <th>right</th>
              <th>width</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((f) => {
              const y = shape.top + (shape.bottom - shape.top) * f;
              const [lo, hi] = shape.spanAt(y);
              return (
                <tr key={f}>
                  <td>{Math.round(f * 100)}%</td>
                  <td>{lo.toFixed(1)}</td>
                  <td>{hi.toFixed(1)}</td>
                  <td>{(hi - lo).toFixed(1)}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      );
    }

    倾斜余量

    const near = spanAt(bottom - 1);
    const above = spanAt(bottom - 9);
    const ratio = (near[1] - near[0]) / (above[1] - above[0]);
    tiltScale = clamp(1 - 1.9 * (ratio - 0.36), 0.15, 1);

    平底会得到接近 1 的比值,因为紧贴底部的轮廓几乎和底部一样宽。圆底得到小得多的比值。

    之所以要在意,是因为平底形状一旦倾斜就会显得不对——底面翘起来,重量感也跟着消失。量底部意味着没有形状需要手写倾斜系数,包括明天才会出现的形状。

    测得的值:tofu、cloud、star、bell、bot 为 0.15,ghost 约 0.17,pill 约 0.36,pebble 约 0.88,圆底的形状为 1。

    极坐标环

    轮廓被重采样成 96 个固定角度的点:从中心射出射线,取最远交点。固定角度意味着两个不同形状有对应的点,所以它们之间的形变——或者把身体收成腰带用的圆——就是半径的直线插值。

    腰带半径

    粒子轨道用最宽的水平半宽,而不是外半径。在外半径上绕行会让卫星看起来离开带角的形状,因为角上的距离并不是身体视觉上结束的地方。

    面部拟合

    脸是找出来的,不是摆上去的。两级网格搜索在轮廓内寻找最大且舒服的椭圆:

    1. 粗扫描,8 单位网格,x ∈ [−16, 16],y ∈ [−56, 56]
    2. 在胜者周围以 2 单位细化
    3. 每个位置试七种长宽比,从 1:1.45 到 1.45:1

    评分奖励离轮廓的余量和椭圆周界上最紧的点,并惩罚偏离中心,这样有两个同样宽裕位置的形状会选那个看起来更刻意的。

    回报是三角形自然得到低脸、胶囊自然得到高脸,两者都没有被特殊处理——你明天发明的形状也会免费得到一张像样的脸。

    拟合椭圆不是脸

    这一点值得单独说,因为它很容易搞错。拟合器返回的是最大内切椭圆,对圆形身体来说几乎就是整个剪影。直接拿它当面部盒,眼睛会靠近轮廓并且离得很远。

    三个常量把可用空间变成真正的脸:脸占拟合椭圆的 58%,坐在拟合中心上方 26% 的高度处,两眼间距是脸半宽的一半。锚在拟合中心的眼睛会落在身体腰部,读起来像躯干而不是头。

    惰性

    形状在第一次使用时才推导。面部拟合是带点到轮廓距离查询的网格搜索,eager 地构建全部形状的代价远高于任何页面所需。

    接下来