介绍一个基于有向距离场(SDF)的地图碰撞系统

啊,这是个不错的思路:+1:可以深入挖掘一下:stuck_out_tongue_winking_eye:
顺带gridLen指代一个单位格子在场景中的实际长度

这个地方为什么先乘个0.5再标准化?

这里为什么选择迭代3次?希望大神指教~~~

应该是arr.push(r<128&&g<128&&b<128);

啊这,如果要归一化的话就不需要再乘0.5了,感谢指正。
不过我仔细看了一下,发现这一块的代码是有问题的,并不需要做归一化。可以看一下这个新的工程:
sdfDemo.zip (996.1 KB)

代码更新

calGradient(pos:Vec3):Vec3{
    var delta=1;
    var dis0 = this.calPointDis(new Vec3(pos.x+delta,0,pos.z));
    var dis1 = this.calPointDis(new Vec3(pos.x-delta,0,pos.z));
    var dis2 = this.calPointDis(new Vec3(pos.x,0,pos.z+delta));
    var dis3 = this.calPointDis(new Vec3(pos.x,0,pos.z-delta));
    var result = new Vec3(dis0-dis1,0,dis2-dis3).multiplyScalar(0.5);
    //console.log(StringUtils.format("dis0=%s,dis1=%s,dis2=%s,dis3=%s,result=%s",dis0,dis1,dis2,dis3,result));
    return result;
}

这样写才符合求导公式

因为delta=1,所以最后可以直接*0.5
加上归一化是错的。可以看到去除归一化后,角色贴墙移动比原先稳定了许多。

==================================

第二个问题,这段我直接copy了《腾讯游戏开发精粹》的相关代码:

我的理解是,角色触碰墙壁进行位置修正后,可能会遇到修正后点的SD依然小于自身体积的情况(例如90度的转角),这时会试图沿着法线向量“退回”到安全区域。但是如前面的公式所示,法线计算的结果并不精准,有可能计算出来的结果依然不处于安全区域,这时候需要进行多次回退计算。计算的次数越多,目标点落在安全区域的概率就越大。
当然,每帧总计4轮的计算确实是一笔挺大的开销,我试过把迭代次数设为1,似乎也没有出什么问题。不过安全起见最后我还是保留了最多3次的循环验证。

1赞

多谢指正。因为最开始的一版存储的是通行数据,发布的时候这块用的是老代码:joy:

试了一下,delta=1,去掉归一化,虽然贴墙不会那么抖,但是帧数低的时候在墙角会出现穿墙的情况。30帧及以下。不知道是不是我改了其它参数的缘故

感谢分享,mark mark

我用2d改写了下,发现在90度夹角会穿墙,大佬们能提供点建议吗

质量贴,mark

腾讯游戏开发精粹 第一章讲的就是这个吧

mark~~~~~~~~~~~~~~~~~~~~~~~~~~

给力,学习了!

最近刚好读了一些字体sdf渲染相关文章,计算有向距离的算法可以参考这篇文章,时间复杂度可以从O(N^2)优化到O(N)。
https://zhuanlan.zhihu.com/p/65421383

1赞

感谢大佬分享

感谢大佬分享

战略mark

mark a

战略mark

不明则厉!mark!