与复杂几何体碰撞和滑动球体

Posted

技术标签:

【中文标题】与复杂几何体碰撞和滑动球体【英文标题】:Collide and slide a sphere against complex geometry 【发布时间】:2012-10-09 09:41:43 【问题描述】:

我可以使用一些帮助来确定碰撞响应。我正在尝试实现在幻灯片 4 到 10 上呈现的 in this paper。碰撞检测有效,并且碰撞实体 确实 沿着碰撞平面滑动,但速度严重降低。我不确定我是否正确地将剩余速度投影到碰撞平面上。

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 之后,我将 vnewVelocity 都可视化了,它们看起来应该是这样的: 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 总是跑到零,所以总是有冲突。也许这会减慢速度?

对基础数学有更好理解的人可以看看吗?

谢谢!

编辑:

第一次迭代后的向量说明:

盒子与墙壁发生碰撞(由于背面剔除,此屏幕截图中不可见)

【问题讨论】:

【参考方案1】:

发现问题:我忘记在每次迭代开始时重置 packet.collisionTime,这是它减慢了速度的原因。它现在按预期工作。也许代码对其他人有帮助。

【讨论】:

以上是关于与复杂几何体碰撞和滑动球体的主要内容,如果未能解决你的问题,请参考以下文章

PCL 最小包围盒

Ammo.js 自定义网格与球体碰撞

向量几何在游戏编程中的使用4

碰撞工作在PC模拟器上但不在Android设备上

Unity 3D 碰撞检测

2个物体之间的子弹碰撞回调