Babylon.jsで簡単に3D空間のドラッグ&ドロップ(改善版)
前回の記事の改善版です。
前回、『このPointerDragBehaviorを使ったドラッグ&ドロップは、ちょっと甘いところがあるんですよね。物理エンジンとあわせて使うことをあんまり意識していないのだと思うのですが、変な動きすることがあります。』と書いたのですが、この点を改良してみました。
ベースはPointerDragBehaviorに乗っかりますが、
pointerDragBehavior.moveAttached = false;
として、PointerDragBehaviorの振る舞いは止めています。その上でpointerDragBehaviorのonDragStartObservable、onDragObservable、onDragEndObservableに動作を加えています。
ドラッグスタート時にマウス(とカメラを結んだ光線)と対象オブジェクトの交点を計算して、そこにmarkオブジェクトを置きます。そのmarkオブジェクトと対象オブジェクトをjointで繋ぎます。
ドラッグしたら、markオブジェクトをマウスの動きに応じて移動します。(この辺りにコツがあるのですが、、、細かい点はソースをみて欲しいです。)そうすると、markオブジェクトに引きずられて対象オブジェクトが移動するのです。
点と点をjointでつないでいるので、対象オブジェクトをマウスでつかんだ点を持っているような感覚が表現できます。PointerDragBehaviorを素朴に使うと、その辺り、動きが変なのですよね。
See the Pen babylon drag test v7 by mizukoshi akiya (@akiyah) on CodePen.
jointを作る時に、BABYLON.PhysicsJoint.PointToPointJointを使ったのですが、この時のパラメーターとしてmaxForceを小さめにして指定しています。こうしないとマウスでドラッグした瞬間に対象オブジェクトがブルっと震えて隣り合ったオブジェクトを弾き飛ばすと言う振る舞いをしてしまったんですよね。詳細な振る舞いはわかっていないのですが、今のところmaxForceを小さめにしておけば良いので、保留にしています。(maxForceを小さめにすることで動きがちょっと悪くなるのですが、それはトレードオフとして今は目をつぶっています。)
ひとまずここまででBabylon.jsのドラッグ&ドロップは一区切りにしようと思っていましたが、テンセグリティに応用する時に二つのポインターを扱うという欲望も出てきてしまったので、もうちょっとやってみます。