1. ホーム
  2. javascript

[解決済み] three.jsで衝突を検出する方法は?

2022-02-19 17:20:24

質問

three.jsを使っています。

私のシーンには2つのメッシュジオメトリがあります。

これらのジオメトリが交差している場合(または が交差する これを衝突として検出したい。

three.jsで衝突判定を行うにはどうしたらよいですか?もしthree.jsに衝突判定機能がない場合、three.jsと組み合わせて使える他のライブラリはありますか?

どのように解決するのですか?

Three.jsでは、ユーティリティのCollisionUtils.jsとCollisions.jsはもうサポートされていないようで、mrdoob(three.jsの作者)自身がthree.jsの最新版に更新して、代わりにこの目的のためにレイクラスを使用するよう推奨しています。以下は、そのための一つの方法です。

例えば、quot;Player"というメッシュが、quot;collidableMeshList"という配列に含まれるメッシュと交差しているかどうかをチェックしたいとしましょう。プレイヤーメッシュの座標 (Player.position) から始まり、プレイヤーメッシュのジオメトリの各頂点に向かって伸びる一連の光線を作成することができます。各レイには "intersectObjects" というメソッドがあり、レイが交差したオブジェクトの配列と、各オブジェクトまでの距離 (レイの原点から測定) が返されます。交差点までの距離がプレイヤーの位置とジオメトリの頂点間の距離より小さい場合、衝突はプレイヤーのメッシュの内部で発生したことになります。

に動作例を掲載しました。

http://stemkoski.github.io/Three.js/Collision-Detection.html

赤いワイヤーフレームキューブは矢印キーで移動、W/A/S/Dで回転させることができます。 青いキューブの1つと交差すると、上記のように交差するごとに1回、画面上部に"Hit"という文字が表示されます。 コードの重要な部分は以下の通りです。

for (var vertexIndex = 0; vertexIndex < Player.geometry.vertices.length; vertexIndex++)
{       
    var localVertex = Player.geometry.vertices[vertexIndex].clone();
    var globalVertex = Player.matrix.multiplyVector3(localVertex);
    var directionVector = globalVertex.subSelf( Player.position );

    var ray = new THREE.Ray( Player.position, directionVector.clone().normalize() );
    var collisionResults = ray.intersectObjects( collidableMeshList );
    if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() ) 
    {
        // a collision occurred... do something...
    }
}

この特殊な方法には、2つの潜在的な問題があります。

(1) 光線の原点がメッシュM内にある場合、光線とMの衝突結果が返されない。

(2)プレイヤーメッシュに対して小さなオブジェクトは、様々な光線の間をすり抜けてしまい、衝突が登録されない可能性があります。 この問題の可能性を減らすには、小さなオブジェクトが光線を作り、その視点から衝突検出を行うようにコードを書くか、メッシュに多くの頂点を含める(例えば、CubeGeometry(100, 100, 100, 20, 20)ではなく、CubeGeometry (100, 100, 1, 1, 1) を使用するなど)、二つのアプローチが考えられます。後者の方法は、おそらくパフォーマンスヒットを引き起こすので、控えめに使用することをお勧めします。

この質問に対して、他の方が解決策を寄稿してくださることを期待しています。 私自身、ここで説明した解決策を開発するまで、かなりの間、この問題に苦心しました。