これまで何度か、Babylon.js 物理エンジンHavokが使用された Physics V2 を試してきたが、できないことがあった。
それは『モーター』。
Physics V1 には、モーターがあったが、Physics V2 にはない。
Babylon.js v7 が公開されても様子が変わらない様子だった。
しかし、正確にはドキュメントにそれがあるように書かれていないということが分かった。
コミュニティに聞いてみたりなどして、状況が分かったので一通りまとめておく。
参考
事の経緯
実装だけ知りたい人は読み飛ばしてください。
2023年10月
「Physics V2 で ロボットを歩かせられないか」という意図で、物体の位置を任意に変更できないか質問。
その際に共有したのがこの画像。
参考として、ゾイドの動画など共有したりした。
結論はここでは出ず、Babylon.jsのフォーラムで質問することになった。
https://forum.babylonjs.com/t/havok-physics-on-walk/45184
ここでは、制約(Constraint)をうまく使うことできるらしいということ答えがあった。
この時直接的に答えてくれた方はこのトピックでは応答が無くなってしまった。
同じ時期にモーターが、Physics V1 にはあるが、Physics V2 では紹介されていないということが分かった。
この頃はどうにもならなそうなのが分かったので、一旦放置。
以降しばらく、サーバー上での物理演算を先に処理してしまうパターンなんかをやっていた。
2024年2月
モータが導入されるまでまだまだ時間を要しそうであることが分かったので、試験的にモーターのような1方向に物体を動かすことを試したりしていた。
https://playground.babylonjs.com/#Z8HTUN#852
この時は、setAngularVelocity
で物体を動かすことで、実装した。
この時、スライダクランク機構など作った。(今プレイグラウンドを見ると、吹き飛ぶようになってしまっているけども)
https://playground.babylonjs.com/#Z8HTUN#855
この時もフォーラムに投稿して、実装方法を伺ったりしている。
https://forum.babylonjs.com/t/want-to-reproduce-the-movement-like-a-motor/47801
2024年4月13日
Babylon.js v7 がリリースされた。
しかし、ドキュメント(紹介)を見るにモーターの仕様はまだない。
なので、リポジトリの方でIssueを立ててみた。
https://github.com/BabylonJS/Babylon.js/issues/14979
結論からすると、一旦フォーラムで現状をまとめてくれということだった。
なので、フォーラムへ再投稿。
https://forum.babylonjs.com/t/are-motorized-constraints-still-being-introduced/49617
ここでの答えは、Physics6DoFConstraint.setAxisMotor
があるということ。
機能紹介には書いていなかったりする。
https://doc.babylonjs.com/features/featuresDeepDive/physics/constraints
検索ボックスに、setAxisMotor と入れても出てこないが、Class Physics6DoFConstraint
のドキュメントには記載がある。
(10月の時点で記載があったのかは確認していない。)
https://doc.babylonjs.com/typedoc/classes/BABYLON.Physics6DoFConstraint
そしてこのAPI正直使い方よくわからなくて(というか設定が面倒すぎる)とあまり触ってこなかったものだった。
(そして、HingeConstraint
などよく使いそうなものには、メソッドが生えていなかったりする。)
といろいろありつつ、モーターを使えることは分かった。
親切に教えてくれたフォーラムの型に感謝したい。
しかし、問題はまだあり、モーターの回転方法を拾う方法がわからない。
これは同じトピックでそのまま聞いてみたが、Physics6DoFConstraint.setAxisMotor
を教えてくれた人も知らなかった。
2024年4月20日
この辺りで、Babylon.jsを主題において質問する/調べるのはもうおそらく無理なのが見えてきていた。
なので、クオータニオンとかの数学レベルとかUnity関連の計算処理の方法を参考に調査をしていた。
おそらくできるだろうとは思いつつ、4日ほど調べることになってしまった。
途中CopilotChatとChatGPTも駆使したけど、いいとこ行くんだけど正解は出ない感じが続いてた。
でいろいろあって、Qiitaの記事を見つけた。
Qiita - 【THREE.js】Quaternionでローカル座標の回転差分を求める
これで、2物体間がなす角度の処理方法が分かった。
少し手直ししてBabylon.jsに適応させた。
実装
モーターの使い方
以下のようにモーターが使える。
1 | // 物体1 親 |
こんな具合で、Physics6DoFConstraint
を使って、モーターを作成できる。
setAxisMotorMaxForce を下げると自重で回転してしまったり、外力で動いてしまったりする。
トルクを0付近にしてあげると「ある瞬間からラグドールみたいになる」ということもできるだろう。
Physics6DoFConstraint での制限は、プロパティは多数あるがこのくらいが使いやすいのではないだろうか。
2物体のなす角度を取得する
以下の処理をかませると、2物体のクオータニオンの差分から、角度(ラジアン)を取得できる。
1 | function getAegleFromQuaternions( |
使う側はこんな感じ。
1 | const box1To2ConstraintAxis = new BABYLON.Vector3(0, 0, 1); |
この場合、物体2つのZ軸を基準にした角度が取得できる。
これを使ってプレイグラウンドでサンプルを作った。
落ちてくる球体の中で、常に90度保ちながら左右に回転させている。
物理エンジンが動いているので、重いもの(大きいもの)が当たると、首が下がるが、フィードバックが効いているのでもとに戻る動きをする。
https://playground.babylonjs.com/#XTFBWG
というわけで、Babylon.js Physics V2 Havok でモーターを使う方法がわかった。
さらに物体間のなす角まで取得する方法もわかったので、いろいろとこの半年くらい時間を使っていたことが解決した。
途中チェビシェフリンク機構なども作ったりしていたが、これはこれで限界が見えていたので、これからはモーターを使っていく。
今回作ったデモで、落ちてくる球を振り払って飛んでいく姿を見ていたら、昔トミーから出ていたヤキューマンのことを思い出したので、気がむいたら作る。(投手だけやもしれないけど)
では。