前々回アップした、XPBD(extended position-based dynamics) による Cloth シミュレーションの解説です。今回はマウス操作について説明しています。
実行結果
cloth の上でマウスをクリックしドラッグすると、cloth が引っ張られた状態になります。
1 mouse down
mesh 上をマウスでクリックして、クリックされた mesh の index や位置情報を取得する。mesh 情報の取得には、Babylon.js の raycast 機能を使用する。
Scene の onPointerDown property は、scene 上をマウスでクリックすると、
IPointerEvent, PickingInfo, PointerEventTypes パラメータを持つコールバックを
起す。
scene.onPointerDown = function (event, pickInfo){ //console.log(“mouseDown pickInfo", pickInfo.hit); if (pickInfo.hit == true) { //console.log(“mouseDown pickInfo id", pickInfo.pickedMesh.id); //console.log(“mouseDown pickInfo faceId", pickInfo.faceId); gGrabber.start(pickInfo); camera.detachControl(canvas); } }
event が IPointerEvent に、pickInfo が PickingInfo に相当する。PointerEventTypes は使用していない。マウスクリックが起こると、function 内の処理が実行される。
mesh の情報は、pickInfo から得られる。マウスをクリックすると、クリック位置から画面に垂直奥方向に ray が発せられる。そこに mesh があれば、pickInfo.hit が true になる。true の場合は、
pickInfo.pickedMesh: ray が当たった mesh data
pickInfo.faceId: ray が当たった mesh の face(triangle)番号
pickInfo.pickedPoint: mesh 上で ray が当たった位置
などが得られる。
ray の情報も得られる。
pickInfo.ray.origin:クリックした mouse の位置
pickInfo.ray.direction:ray の方向ベクトル
ray の情報は、mesh が無い場合でも得られる。
mouse down をしたとき、以下の処理を行う。
- クリックした位置(下図の)に対応する mesh 上の位置(下図の)と、mesh index を取得し、その mesh point の position に設定する。
- mouse drag 中に mesh が移動しないように、カメラコントロールをオフにする。
camera.detachControl(canvas)
mesh の vertex point の position 設定は、以下のように行なっている。
・mesh 上の位置の取得
の座標(マウスポインターの座標)は ray.origin、
の座標(対応する mesh 上の座標)は pickInfo.pickedPoint、
から得られる。 はウィンドウの原点である。
・mesh index の取得
mesh の拡大図
のある triangle の face 番号は、pickInfo.faceId から得られる。
と triangle の座標 , , との距離が最小となる index を見つけ、それを grabId とする。
これを行なっている部分が、Grabber.start(pickInfo) である。
次に、 を uniform data、grabId を grabIdBuffer data として compute shader startGrab に送り、ここで grabId の point の invMass を 0(重力の影響を受けない)、position を に設定する。
これを行なっている部分が、this.physicsObject.startGrab(pos) である。
this.physicsObject には、Cloth が設定されている。
2 mouse move
mouse move した時の処理は、scene.onPointerMove で行う。
この場合は、pickInfo.hit は常に false の状態である。移動後の mesh point の座標は、ray 情報から得る。
mouse move した様子
drag したマウスポインターの座標 は、pickInfo.ray.origin から得られる。
マウスポインターの移動に対応した mesh point の座標 は、以下のようにする。
= pickInfo.ray.direction x distance
distance : mouse down 時の マウスポインターと mesh との距離(this.distance = pickInfo.distance)
これを行なっている部分が、Grabber.move(pickInfo) である。
次に、移動後の mesh point の座標 を、uniform data として compute shader moveGrabbed に送り、grabId の point の position を に設定する。
これを行なっている部分が、Cloth.moveGrabbed(pos, vel) である。(vel は使用していない。)
また、Grabber.move(pickInfo)では、mesh point の速度(this.vel)の計算も行なっている。
3 mouse up
drag を終了し mouse up を行うと、以下の処理をする。(scene.onPointerUP)
1 compute shader で、grab された mesh point の vel、invMass を設定する。 (this.physicsObject.endGrab(this,prevPos, this.vel) の部分)
mouse move で計算した mesh point の速度 vel(this.vel) を uniform data として
compute shader endGrab に送り、grabId の point の velocity を vel に設定
する。
また、grabId の point の invMass (0 に設定されている) を元の
invMass (grabInvMass) に戻す。
その後、grabId を初期値(-1)に戻す。
2 this,physicsObject を null にする。
3 カメラコントロールをオン(camera.attachControl true)にする。