
環境
- three.js
- pixiv/three-vrm
はじめに
AItuber-kitでの待機モーションは、VRMAモーションのidle_loop.vrmaやサッケード(急速眼球運動)、まばたきなどで動きが工夫されています。 止まった絵にならないよう配慮されており、十分に自然に見えます。
しかし長時間見ていると、どこか規則性を感じることがあります。 ループしているような印象というか、「生きている」という感覚が少し弱い。
配信で拝見したAITuber「零音ほのか」さんは、待機状態でもどこか躍動感があり、パターンを感じさせません。 そこで、その実装思想をVRMにも応用できないか試してみました。
やっぱりsin波では足りなかった
最初は単純に sin 波で揺らしてみました。
Math.sin(t) * 係数
身体の回転や位置に適用すると確かに“揺れている”感じは出ます。 しかし sin 波は周期関数です。 一定時間で必ず同じ動きを繰り返します。
長く見ていると、その規則性を無意識に認識してしまい、 機械的な印象が残りました。
Perlinノイズ
これまで調べた事がなかったのですが、sin波より不規則な波が作れるという認識です。
使用したのは josephg さんの noisejs です。
https://github.com/josephg/noisejs
fBm
規則性を弱めるために、sin波による簡易実装ではなく本家ほのかさんの実装通りにfBm(フラクタルブラウン運動)も試しました。
noise発生源をnoisejsのperlin2に変えた形です。
実装例(ほのかさんのpythonによるfbmコードとほぼ同じ)
fbm(t, octaves = 3, lacunarity = 2.0, persistence = 0.5, yOffset = 0.0) {
let value = 0.0;
let amp = 1.0;
let freq = 1.0;
let maxVal = 0.0;
for (let i = 0; i < octaves; i++) {
value += amp * noise.perlin2(t * freq, yOffset);
maxVal += amp;
amp *= persistence;
freq *= lacunarity;
}
return maxVal > 0.0 ? value / maxVal : 0.0;
}
周波数を段階的に上げながら、振幅を減衰させて足し合わせているらしいのですが
出てくるものはわかっても、中身はよくわからない。
適用箇所
- 身体のわずかな揺れ(fbm)
- 首の微小な回転(Perlin Noise)
- 目の瞬き間隔の不定期化(Perlin Noise)
特に瞬き間隔にノイズを使うことで、 「規則的なまばたき」から「生理的な揺らぎ」へと印象が変わりました。
結果
sin波と比べて、長時間見てもパターンを感じにくくなりました。
揺れ幅はごく小さいものです。 しかしその微小な揺らぎが加わることで、 立っているだけの状態から、そこにいる状態へと印象が変わります。
実際の動きが確認できます。
アリシア・ソリッドアバターによる稼働確認URL
👉https://kinkuman.net/threejs/
(three.jsとthree-VRM.jsによるモーション確認のみですが、グリーンバックがないところで右クリックしてソース見れます。)
- https://kinkuman.net/threejs/posture-controller.jsが体関連
- https://kinkuman.net/threejs/eye-noise-controller.jsが目
まとめ
- sin波は規則的
- fBm、Perlinは非周期的
- 生き物らしさは不規則な「揺らぎ」にある
数学的な理解が完全でなくても、 「周期を崩す」という意識だけで印象は大きく変わります。
