具有分离轴定理的多边形三角剖分

问题描述

我正在学习用于 2D 碰撞和响应的分离轴定理。我想支持与凹多边形的碰撞,所以我正在使用 earcut 对多边形进行三角剖分并测试每个三角形。

不幸的是,它似乎仍然将凹多边形视为凸多边形,例如,给定坐标 (0,0)(0,50)(40,50)(10,40),碰撞表现得好像 (10,40) 点不存在,有效地使它成为一个三角形。我检查了三角坐标,它们看起来很正常:[1,3,2,1](每个数字代表点的索引)。

此外,我的 SAT 实现在发现不重叠的“阴影”时返回 false,但通过检查每个三角形相互之间的关系,单个三角形在其父多边形发生碰撞时可能不重叠。响应中也存在类似的问题,我抓住了最小的重叠差异并将碰撞器推回,但与单个三角形的最小重叠可能并不代表真正的重叠量。

我该如何解决这两个问题?

jsfiddlehttps://jsfiddle.net/ay51n4we/

注意:我在jsfiddle的末尾包含了earcut库,我的代码是第291行

三角剖分

triangulate(){
    let pvertices = [];
    for(let v of this.vertices){
        pvertices.push(v.x,v.y);
    }
    this.tpoints = earcut(pvertices); // triangulated vertices
    this.tsub = []; // triangulated polygons for collision
    for(let i = 0; i < this.tpoints.length; i+=3){
        this.tsub.push([this.vertices[this.tpoints[i]],this.vertices[this.tpoints[i+1]],this.vertices[this.tpoints[i+2]]]);
    }
}

碰撞检测

let sprite1 = this;
let sprite2 = cand;

for (let sprite = 0; sprite < 2; sprite++) {
    if (sprite == 1) {
        // flip to avoid repetitive code
        sprite1 = cand;
        sprite2 = this;
    }

    for(let s = 0; s < sprite1.tsub.length; s++){
        for (let a = 0; a < sprite1.tsub[s].length; a++) {
            const b = (a + 1) % sprite1.tsub[s].length;

            // normal to sprite edge (axis projection)
            const ap = new Vector(-(sprite1.tsub[s][b].y - sprite1.tsub[s][a].y),sprite1.tsub[s][b].x - sprite1.tsub[s][a].x);

            // find min max for both sprites
            let min1,max1,min2,max2;

            for (let t of sprite1.tsub) {
                for(let p of t){
                    let q = ap.dot(p);
                    min1 = Math.min(min1 ?? q,q);
                    max1 = Math.max(max1 ?? q,q);
                    }
            }
            for (let t of sprite2.tsub) {
                for(let p of t){
                    let q = ap.dot(p);
                    min2 = Math.min(min2 ?? q,q);
                    max2 = Math.max(max2 ?? q,q);
                }
            }

            if (!(max2 >= min1 && max1 >= min2))
                return false;
        }
    }
}

return true;

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)