2

衝突応答を理解するのに役立つことがあります。この論文のスライド 4 から 10 に提示されている内容を実装しようとしています。衝突検出は機能し、衝突エンティティ衝突面に沿ってスライドしますが、速度は大幅に低下します。衝突面に残った速度を適切に投影しているかどうかはわかりません。

class CollisionPacket {
    // INPUT:
    colliderRadius: vec3;
    colliderPosition: vec3;
    colliderVelocity: vec3;

    // OUTPUT:    
    collisionFound: bool;
    collisionTime: number;  // how far can we travel before we collide?
    collisionPoint: vec3;   // point on triangle where collision ocurred
    collisionNormal: vec3;  // normal of nearest collided triangle
}

collideAndSlide(position: vec3, velocity: vec3, radius: number): vec3 {
    var packet = new CollisionPacket();

    packet.colliderRadius = radius;
    packet.colliderPosition = position;
    packet.colliderVelocity = velocity;

    packet.collisionTime = 0.0;
    packet.collisionFound = false;

    var maxIterations = 5;

    do {
        // check nearby triangles for collisions
        this.collideWorld(packet);

        var newPosition = packet.colliderPosition.copy();
        var newVelocity = packet.colliderVelocity.copy();

        if (packet.collisionFound) {
            // scale velocity vector to collide with nearest triangle
            var scaledVelocity = packet.colliderVelocity.copy().scale(packet.collisionTime);

            // move a tiny bit away from collision along collision normal
            scaledVelocity.add(packet.collisionNormal.copy().scale(0.001));

            // add scaled velocity to position
            newPosition.add(scaledVelocity);

            // and remove it from leftover velocity
            newVelocity.subtract(scaledVelocity);

            // extract part of velocity vector which is perpendicular to collision plane (CORRECT?)
            var v = packet.collisionNormal.copy().scale(vec3.dot(newVelocity, packet.collisionNormal));

            // remove that part from velocity vector
            newVelocity = vec3.difference(newVelocity, v);

            // update values for next iteration
            packet.colliderPosition = newPosition;
            packet.colliderVelocity = newVelocity;
        }
        else {
            // no collision, move as requested
            newPosition.add(packet.colliderVelocity);
        }
    } while (--maxIterations > 0 && packet.collisionFound)

    return newPosition;
}

vを差し引いた後のvnewVelocityの両方を視覚化したところ、本来あるべき姿が見えました。

次のように、再帰を行う代わりに newVelocity を newPosition に直接追加すると、次のようなります。

                ...

                // remove that part from velocity vector
                newVelocity = vec3.difference(newVelocity, v);

                newPosition.add(newVelocity);
        }
        else {
                // no collision, move as requested
                newPosition.add(packet.colliderVelocity);
        }
    } while (false)

エンティティは速度を落とさずにスライドしているので、ベクトルは問題ないと確信しています。

ただし、maxIterationsは常にゼロになるため、常に衝突が発生します。多分それはそれを遅くしていますか?

基礎となる数学をよりよく理解している人は見てくれるでしょうか?

ありがとうございました!

編集:

最初の反復後のベクトルの図:

ここに画像の説明を入力

ボックスが壁に衝突しています (このスクリーンショットでは背面カリングにより見えません)

4

1 に答える 1

0

問題が見つかりました: 各反復の開始時に packet.collisionTime をリセットするのを忘れていました。これが原因ですべてが遅くなりました。現在、期待どおりに動作しています。たぶん、コードは他の誰かに役立ちます。

于 2012-10-19T16:15:25.450 に答える