ryo-i / next-three-js-test

next-three-js-test.vercel.app
4 stars 0 forks source link

物理エンジンと連携する #14

Open ryo-i opened 1 year ago

ryo-i commented 1 year ago

物理エンジンのドキュメントをいくつか巡回したがThree.jsと連携した事例が意外に少なかった。 cannon.jsの後継のcannon-esのドキュメントは事例があったのでこちらで初体験してみる。

ドキュメント https://pmndrs.github.io/cannon-es/docs/index.html

サンプル https://pmndrs.github.io/cannon-es/

GitHub https://github.com/pmndrs/cannon-es

npm https://www.npmjs.com/package/cannon-es


他参考 https://threejs.org/docs/#manual/ja/introduction/Libraries-and-Plugins https://qiita.com/naotaro0123/items/96a0a059ce2983ae9da7

ryo-i commented 1 year ago

cannon-esのドキュメントではcannon-esのposition、quaternionをそのままthree.jsに設定していた

  sphereMesh.position.copy(sphereBody.position)
  sphereMesh.quaternion.copy(sphereBody.quaternion)

TS環境では下記の型エラーになる

Argument of type 'Vec3' is not assignable to parameter of type 'Vector3'.
  Type 'Vec3' is missing the following properties from type 'Vector3': isVector3, setScalar, setX, setY, and 59 more.

Argument of type 'import("math/Quaternion").Quaternion' is not assignable to parameter of type 'THREE.Quaternion'.
  Type 'Quaternion' is missing the following properties from type 'Quaternion': isQuaternion, setFromRotationMatrix, setFromUnitVectors, angleTo, and 18 more.

キャスト関数を作る

const cannonVec3ToThree = (vec3) => {
  return new THREE.Vector3(vec3.x, vec3.y, vec3.z);
};

const cannonQuaternionToThree = (quaternion) => {
  return new THREE.Quaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w);
};

キャスト関数を実行することでエラーがなくなった

sphereMesh.position.copy(cannonVec3ToThree(sphereBody.position));
sphereMesh.quaternion.copy(cannonQuaternionToThree(sphereBody.quaternion));
ryo-i commented 12 months ago

衝突設定はContactMaterialとaddContactMaterialが衝突時に跳ねる設定をしていそう

https://pmndrs.github.io/cannon-es/docs/classes/ContactMaterial.html https://pmndrs.github.io/cannon-es/docs/classes/World.html#addContactMaterial

参考 https://pmndrs.github.io/cannon-es/examples/bounce https://github.com/pmndrs/cannon-es/blob/master/examples/bounce.html https://liginc.co.jp/378448

ryo-i commented 12 months ago

キューブの影をつけたい

シャドー設定 https://threejs.org/manual/#ja/shadows https://threejs.org/docs/?q=shadow#api/en/lights/shadows/DirectionalLightShadow

ryo-i commented 12 months ago

このサンプルでは物体が転がっているので方法を調べたい https://pmndrs.github.io/cannon-es/examples/worker_sharedarraybuffer https://github.com/pmndrs/cannon-es/blob/master/examples/worker_sharedarraybuffer.html

ryo-i commented 11 months ago

床のsetFromEulerを打ち替えて傾けるがやはり転がらないまま落ちる。そういうことじゃないんだなーと知る。 物理的にはこちらの方がすごい現象なのだけどw (あと床以外も地面なことがわかった)

床を超えた物体ははるか彼方まだそのまま滑っていく 物体のsetFromEulerも傾けてみたが転がらない(重心の概念がない)

ryo-i commented 11 months ago

Cannon-esのshapeはThree.jsのジオメトリに比べて種類が少ないようで、8面体の形状はなさそうだった

Shape

https://pmndrs.github.io/cannon-es/docs/classes/Shape.html

また、この記事にあるようにボディに対してジオメトリのサイズを倍にしないとサイズが合わなくて宙に浮いた状態になっていた https://blog.nijibox.jp/article/hello-threejs-physics/

ryo-i commented 11 months ago

velocityは角速度というらしい。

angularDampingで減衰率を設定。それ以外の設定値は揃えてある。 angularDampingの設定値は0.01→0.5→0.99で、値が少ないほどよく跳ねることがわかった。

→参考 https://qiita.com/o_tyazuke/items/3481ef1a31b2a4888f5d

次はfrictionの摩擦係数を触ってみる予定


あとはユーザーの操作に紐つけたり、衝突を感知して音が出せるようになりたい。

→参考 https://qiita.com/kob58im/items/5d1d4acaa1fac44c8eed https://qiita.com/kob58im/items/3ef951ec2183021b3025

今は個体をいじってるけど、そのうち液体や気体もあやつれるといいなぁ(そっちの方がハードルは高そう)

ryo-i commented 11 months ago

衝突判定はbeginContactでできた https://github.com/pmndrs/cannon-es/issues/97

しかし一度の衝突でconsole表示が2回実行された。衝突しているbodyA、bodyBが両方動いている模様。 いろいろ試したがbodyBのidが偶数&奇数の2回だったようなので奇数の時だけ動くようにしてみた。 ここに効果音をつけてみたい。

ryo-i commented 11 months ago

beginContactイベントとTone.jsを連携させて物体の衝突時に音が出るようにでけた! コーン・コン・コロンって感じ♪

beginContactイベントはureEffectの中で実行しているのだが、この中に設定しているフックを使うと初期値のまま更新されなかったため、ひとまずTone.js用の値はlet変数で別で設定しておいた

音の強弱はないようで、どんなに微弱な衝突でも同じ音量 ここら辺も衝突の力を感知してボリュームを下げるとかやりたいな