https://gyazo.com/e182592db2997381abe64a36e0ad97c4
説明
「ポーズをURLで共有」を押すとポーズ情報を付与したURLがコピーされます。
アップデート内容
ポーズをURLで共有
ポーズを共有するときに.jsonファイルを使うのが少し面倒に感じたので直接URLで共有できるようにしました。
例 ) .jsonファイルはTwitterには直接上げられない。
使い方
1. まず今まで通りポージングをさせます。
2. メニューから 実験的機能 -> ポーズをURLで共有 をクリックしてください。
https://gyazo.com/f9ac91c1b7d2497f46d6918a3c08f48d
3. クリップボードにURLがコピーされます。
https://gyazo.com/fbf7b20ec461cdcaaa47b072cbe3cb38
4. URLをペーストしてアクセス。その後VRMモデルを読み込むと自動的に設定されたポーズが読み込まれます。
https://gyazo.com/2d6619af584c543fdf6ad4c6d47af9f5
あくまでも実験的機能なので今後使えなくなる可能性があることをご了承ください。
その他の変更
デフォルトアバターがページ読み込み時に自動的に読み込まれないようになりました。
デフォルトアバターを使用したい場合は メニュー -> デフォルトポーズを読み込み をクリックしてください。
https://gyazo.com/5ea7d31090e8887d0cb1b45c69c3f7c6
上半身IKが首にしか適用されていなかった問題を修正しました。
頭にあるIKを動かすと腰から頭にかけての上半身が動くようになります。
https://gyazo.com/6f527377d3caab8358b666e9f994fca2
ポーズデータの文字列への変換
ポーズデータの話とその文字列への変換の仕組みについてです。
pixiv/three-vrm VRMPose
VRMPoseは
code:json
{
ボーン名 : {
},
}
という構造になっています。
rotationは各ボーンの回転のクォータニオンです。
positionは省略可能です。
VRMへのget/setは以下の関数を使用します。
setPoseを使うときはpojitionを使わないようにしています。
なぜかボーンの位置がずれてしまうため。
code:js
const pose = this.currentVRM.humanoid!.getPose();
Object.keys(pose).forEach((key) => {
delete posekey!.position; });
このVRMPoseをいままではそのままjsonとして出力していました。
code:js
これをURLパラメータに変数として格納します。
つまり文字列に変換します。
まず先頭64bitをヘッダ領域として、ボーンの使用状況を定義します。
各bitの0,1でそのボーンの情報が省略されているか、文字列に含まれているかを示しています。
ポーズで全てのボーンが編集されていることはあまりないため
特に手は大量の関節があるわりに現状編集しずらい
VRMで規定されているボーンは必須、オプショナルを合わせて55種類です。
55bit < 7Byte で足りるのですが、キリが良いのと今後のために余裕を持たせるために64bit = 8Byteを確保しています。
次にデータ部として各ボーンの回転を変換します。
各ボーンの回転は少数の4次元配列で表されているのでこれを自然数の領域に丸めます。
-1.00000... ~ 1.000... -> 0.000... -> 2.000...
0.000... -> 2.000... -> 000 ~ 200
これで、0~200の範囲に収まるはずです。
つまり8bit 0 ~255 で表現できます。
またここで、モデルに含まれていないボーンや初期状態から変更されていないボーンは省略します。
次にヘッダ部分とデータ部分を連結させてutf8コードの文字列にしたあとbase64でエンコードします。
code:js
btoa(String.fromCharCode(...array));
これでそこそこ短い文字列に変換できました。
最悪300文字程度なので短くは無いです。
本当はTwetterの文字数制限140字におさめたかったんですが無理でした。
そもそもURLは文字数制限とは別枠で4000文字ぐらいいけるらしいので意味はなさそうです。
普通に2桁の16進数の固定長文字列とかでよさそうです
その場合は440字になります。
僕が普段愛用しているDiscordだとURLが長いとそれだけTextチャンネルを占有するので意味はあったと思います。
思いたいです。
おわりに
ひさしぶりにbitとか考えた気がします。Cを使っていた時はかなり身近だったので復習になりました。