VR書道システムを作った

こんばんは!
この記事はVRChat Advent Calendar 2021の4日目の記事です。

さて、筆は紙に対してまっすぐ押し引きして書く道具です。この押したり引いたりの動きを入力して立体的な文字を書きました。
空に文字を出現させたり…

演出を加えてみたり…

正直、やってみたらあんまり面白くなかった。

VR筆に比べリアル筆の動きは複雑で引かれる線もそれに応じ多彩です。面白くなさの原因はそこにもありそう。

▼まずはVR筆をリアルなものへ近づけなきゃな、と思ってこんな感じの筆を作りました。

以下、その解説です。

ここで紹介している筆は下記のワールドで触れますので、
是非触ってみてください。

★書道ラボ2
https://vrchat.com/home/launch?worldId=wrld_8230a3db-d40a-48cd-a69b-ebb744fcb87e

★VR書道家ぼっけいさんによるVR書道教室も行われていますのでご紹介。
VR書道家ぼっけいのブログ https://bokkei.net/
ぼっけいさんのツイッター https://twitter.com/bokkeinet

1.筆の毛を曲げました

筆の毛を曲げる方法として今回は頂点シェーダーを用いました。

画像1
▲上図のようにターゲットの位置座標を筆の頂点座標へ渡すことで曲げています。曲がり具合は頂点カラーでいい塩梅に制御。

無題

▲ターゲットはConfigurableJointで筆に追従させています。このJointは対象の動きをローカル座標軸ごとに制御することができます。

たとえば下記画像ではY Motion = Lockedを選択しており、この設定によりY軸方向へターゲットが移動しなくなります。(DynamicBoneのFreeze Axisに似てますね)
X MotionZ MotionLimitedに設定しています。Limitedに設定すると、ターゲットはその軸に対しLinear Limitの値だけ自由に移動します。何かを引きずりまわすのに便利です。

2.筆の毛をひらきました

筆は紙に押しつけたらバサバサと開くものです。筆がまとまっている形状と開いている形状のシェイプキーを作りました。

▲シェイプキーを作るため筆を開いているところ
シェイプキーは筆の根元から紙までの距離を引数としたLerpで切り替えます。

3.抑えの判定を取りました

これはちょっとわかりづらいかも……。
例えば"口"という字を書くとき2画目に筆画の折れ(転折といいます)が出てきます。転折では横画を書いたあとに一度筆を抑えなおし――抑えたまま下へおろします。
このときリアル筆には抑える力(筆の動きを阻害する力)が加わり続けており、筆先はなるべく横だおしになったまま下へと下っていくはずです。
しかし抑えの効かないVR筆では筆先がすぐ進行方向へとならい縦になってしまいます。これでは転折を正しく書くことができません。

イラスト

今回はUpdateで毎フレーム筆と紙との距離をとり前フレームよりも距離が短ければ「抑えている」と判定しています。
先述したとおりVR筆ではターゲットの位置座標をもとに筆先を操作しています。「抑えている」と判定されたときはターゲットの位置を前フレームの位置へとワープさせ、筆の動きが阻害されているように見せかけています。

4.今後の予定

VR筆をリアル筆に近づけるという点においてまだクリアしなければならない事柄は多いです。

イラスト

▲例えばVR筆を使っているうちに上図のようなどうしても書きづらい筆画が出てきました。
リアル筆では方向転換するとき筆先がねじれることで毛が固く締まります。固く締まることで筆の動きが阻害され、次の横画を書くのに適した筆の形状を保つことができていました。

イラスト

▲他にも色々やりたい。

ねじれに加え筆の割れ平筆の実装を考えたとき
「筆をいくつかの束に分け束ごとにそれぞれ形状を変化させる方法」がもっとも都合よいのではと思います。
そうなると筆とターゲットを1対1でしか結べないConfigurableJointは使い勝手がよくありません。(それに時々意味不明な挙動を見せるのが気に入らない)
なので次回はConfugurableJointの代替品を作りたいなと思っています。

それから冒頭で紹介した演出システムもパワーアップさせたいです。
というかそれが本題なんですが、演出をパワーアップするためVR筆を作ったりラボワールドを作ったりしていたら1年が終わってしまった。

イラスト

▲筆の動きを入力して何かを出力するものが書であるなら、出力されるものが線でなくとも書だと言えるんじゃないでしょうか?

書道ラボは書道の技法を入力し、初見でも楽しめる別の何かを出力することを目指しています。
出来て当然のことばかりやっていてもパイの総量は増えないですからね。
ラボメン募集中!!

5.(おまけ)作ったけど実装してないやつ

現行のVR筆には実装出来ていません。

①にじみ
CRTを利用しているのでちょっと重かったのと、Quest対応に不安があったためお蔵入り。紙にしめり気のパラメーターを持たせています。線が引かれた箇所に値を与えしめっていることにします。しめりの値は時間が経つにつれ減じていきます(渇き)。しめりの値に応じ紙のUVをずらし重ねています。Graphics.Blitが来たら作り直して実装予定。
②バシャバシャ
ParticleSystemでした。SimulationSpace = WorldなパーティクルであってもInheritVelocityを良い感じに調整するとSimulationSpace = Localのようにふるまうことを利用し、Emitterが存在する筆先にパーティクルを追従させています。
Worldに存在し且つ筆に追従するパーティクルはSizeBySpeedにより筆の速度を受け取ってSizeを変化させることが出来ます。紙にぶつかった瞬間Sizeを継承したSubEmitterがドバッと表示され、その像を紙に書き込んでいます。
やや重かったのと同期がよろしくないのでお蔵入り。でも楽しいので良い実装方法が思いつけば使えるようにしたいです。
③墨量の変化
筆に墨量のパラメーターを持たせそれに応じて筆の毛の本数を減らしたり、筆のUVにノイズを加えたりして実装していました。現行のVR筆では墨量をどこで調整するか?が思いついておらず未実装です。この時期は硯に触れているあいだ墨量を回復させていましたが操作スイッチが増えるのはあまり良いことではありません(宗教)
④花パーティクル
筆を紙から離したとき花のパーティクルが発生します。1画ごとに筆を立てるという書道の基本の動きを可視化したかったのですが書きづらいと不評だった(確かに)ので未実装。しかし気に入っているのでどこかのタイミングで復活させたいです。

以上です。
ここまで読んでいただきありがとうございました。

この記事が気に入ったらサポートをしてみませんか?