Javascript物理引擎与模拟无限曲线

Javascript物理引擎与模拟无限曲线,javascript,box2d,physics,curve,chipmunk,Javascript,Box2d,Physics,Curve,Chipmunk,我正在尝试用javascript做一个小翅膀 我第一次看到,我正在使用(因为内存泄漏修复)。 简而言之,我将曲线分解为多边形,使其看起来像: 我还尝试了花栗鼠js,我使用片段形状模拟我的地面,如下所示: 在这两种情况下,当一个圆滚动时,我都会在多边形或线段之间的公共点上遇到一些“碰撞”或“碰撞” 我问过花栗鼠,作者说他为片段实现了radius属性以减少这种行为。我试过了,它确实成功了,但并不完美。我仍然有一些颠簸(我必须将半径设置为30px才能获得积极的效果) “凹凸”附加在两个多边形之间的

我正在尝试用javascript做一个小翅膀

我第一次看到,我正在使用(因为内存泄漏修复)。
简而言之,我将曲线分解为多边形,使其看起来像:

我还尝试了花栗鼠js,我使用片段形状模拟我的地面,如下所示:

在这两种情况下,当一个圆滚动时,我都会在多边形或线段之间的公共点上遇到一些“碰撞”或“碰撞”

我问过花栗鼠,作者说他为片段实现了radius属性以减少这种行为。我试过了,它确实成功了,但并不完美。我仍然有一些颠簸(我必须将半径设置为30px才能获得积极的效果)

“凹凸”附加在两个多边形之间的共享点上:

按照我的建议,使用边缘处理技术(他只测试了多边形接触),以避免圆在边缘上碰撞:

还尝试按照Luc的建议添加项目符号选项,但似乎没有任何变化

这是问题的答案。
您可以尝试更改要检查的值:

  • 子弹选项
  • 边缘尺寸
  • 迭代次数
  • 物理学
(仅在最新开发的Chrome上测试)
耐心点(或者改变水平重力),你就会明白我的意思。

这是给感兴趣的人看的。

我最初认为问题可能来自两个相邻线段之间的坡度变化,但由于在多边形的平面上仍然有凸起,我认为问题相当于碰到了多边形的角

我不知道你是否可以设置两组多边形,彼此重叠?只需使用相同的插值计算,并生成第二组多边形,就像下面的图表:你已经建立了红色的多边形集,并通过在红色多边形的中间设置绿色多边形的左顶点,以及在下一个红色多边形中间的右顶点添加绿色集。 !![附图][1]

这应该适用于凹曲线和。。。不管怎样,你都应该飞过凸面

如果这不起作用,请尝试设置大量多边形以构建坡度。使用圆半径的十分之一作为多边形的宽度,甚至可能更小。这样可以减少坡度的不连续性

--编辑 在Box2D.js第5082行(至少)中,您具有PreSolve(接触,歧管)功能,您可以覆盖该功能,以检查歧管(碰撞多边形时推动雪球的方向)是否正确

为此,需要恢复流形向量并将其与曲线的法线进行比较。它应该是这样的(也许不完全是这样):


我想说这个问题已经在Box2D 2.2.0中解决了,请参阅

问题是,除了chainshape之外,box2dweb实际上是从2.2.1a移植的——我不知道box2dweb的闭包


我通过修改Box2D.Collision.b2Collision.collizedPolygonandCircle尝试的任何操作都会导致不稳定的行为。至少有一部分时间(例如,球在随机方向上碰撞,但仅当它缓慢滚动时)。

最好的解决方案是带有重影顶点的边形状,但如果在您使用的版本/端口中不可用,则下一个最好的解决方案类似于您问题中称为“边缘”的图表,但是用一个非常浅的坡度将多边形进一步延伸到地下,就像这条线:

你需要的是一个立方样条线,它保证顶点和坡度的连续性。我实际上使用的是和立方法来弯曲我的地面。这不是问题所在,因为您可以尝试使用具有多个相邻多边形(或线段)的线性坡度,但当圆在边上滚动时,仍然会得到“凹凸”。
Smooth.js
将立方体分别应用于每个维度,并且不会精确处理坡度。看看
getTangent
方法,它执行有限差分
(next\u value-prev\u value)/stride
,而不是正确的数学处理。我不知道
js
,但在
FORTRAN
C#
中,我使用了数值公式()第3.3节,三次样条。让我补充一点,三次样条不仅在值和斜率上建立了连续性,而且在曲率上也建立了连续性。我恐怕这超出了我的能力:/你能用一个方案解释一下吗?我正在使用Smooth.js来弯曲我分组的坡度,它看起来在视觉上和物理上都很有效。我猜问题是两个相邻的多边形共享一些点,请参见更新的问题。我正在设置一个演示,以便能够更加明确。感谢您的想法,但我无法实现它。它还在颠簸。我仍然认为你箱子的角落是问题所在。看-很明显,你会希望你的雪球以垂直于其表面的脉冲反弹。当遇到拐角时,情况并非如此。尝试将雪球设置为子弹体(请参见)。@SuperSkunk,你能看看碰撞时得到的流形,看看它们是否远离曲线曲面的法线吗?我已经更新了我的答案,使我的观点更具可读性。我正在慢慢地达到目的。仍然需要解决如何从预解算曲线的点(请参见TODO注释块)我现在无法处理它,但我明白你的意思,我将在周末尝试一下!你已经得到了一些积极的结果吗?有趣的技术在后,我会尝试,并寻找幽灵顶点。
Box2D.Dynamics.b2ContactListener.prototype.PreSolve = function (contact, oldManifold) {
    // contact instanceof Box2D.Dynamics.Contacts.b2Contact == true
    var localManifold, worldManifold, xA, xB, man_vect, curve_vect, normal_vect, angle;
    localManifold = contact.GetManifold();

    if(localManifold.m_pointCount == 0)
        return; // or raise an exception

    worldManifold = new Box2D.Collision.b2WorldManifold();
    contact.GetWorldManifold( worldManifold );

    // deduce the impulse direction from the manifold points
    man_vect = worldManifold.m_normal.Copy();

    // we need two points close to & surrounding the collision to compute the normal vector
    // not sure this is the right order of magnitude
    xA = worldManifold.m_points[0].x - 0.1;
    xB = worldManifold.m_points[0].x + 0.1;

    man_vect.Normalize();

    // now we have the abscissas let's get the ordinate of these points on the curve
    // the subtraction of these two points will give us a vector parallel to the curve

    var SmoothConfig;

    SmoothConfig = {
        params: {
            method: 'cubic',
            clip: 'mirror',
            cubicTension: 0,
            deepValidation: false
        },
        options: {
            averageLineLength: .5
        }
    }
    // get the points, smooth and smooth config stuff here
    smooth = Smooth(global_points,SmoothConfig);

    curve_vect = new Box2D.Common.Math.b2Vec2(xB, smooth(xB)[1]);
    curve_vect.Subtract(new Box2D.Common.Math.b2Vec2(xA, smooth(xA)[1]));

    // now turn it to have a normal vector, turned upwards
    normal_vect = new Box2D.Common.Math.b2Vec2(-curve_vect.y, curve_vect.x);
    if(normal_vect.y > 0)
        normal_vect.NegativeSelf();
    normal_vect.Normalize();
    worldManifold.m_normal = normal_vect.Copy();

    // and finally compute the angle between the two vectors
    angle = Box2D.Common.Math.b2Math.Dot(man_vect, normal_vect);

    $('#angle').text("" + Math.round(Math.acos(angle)*36000/Math.PI)/100 + "°");
    // here try to  raise an exception if the angle is too big (maybe after a few ms)
    // with different thresholds on the angle value to see if the bumps correspond
    // to a manifold that's not normal enough to your curve 
};