衝突応答を理解するのに役立つことがあります。この論文のスライド 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を差し引いた後のvとnewVelocityの両方を視覚化したところ、本来あるべき姿が見えました。
次のように、再帰を行う代わりに 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は常にゼロになるため、常に衝突が発生します。多分それはそれを遅くしていますか?
基礎となる数学をよりよく理解している人は見てくれるでしょうか?
ありがとうございました!
編集:
最初の反復後のベクトルの図:
ボックスが壁に衝突しています (このスクリーンショットでは背面カリングにより見えません)