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

时间:2012-05-15 10:50:17

标签: javascript box2d physics curve chipmunk

我正试图在javascript中做一个小小的翅膀。

我第一次看到a technique using Box2D,我正在使用closure-web version(由于内存泄漏修复)。
简而言之,我将曲线分解为多边形,因此看起来像:

enter image description here

我也尝试使用Chipmunk-js,我使用分段形状模拟我的地面:

enter image description here

在这两种情况下,当圆形滚动时,我在多边形或线段之间的公共点处遇到一些“崩溃”或“颠簸”。

我向Chipmunk询问过这个问题,作者说他为该段实现了一个radius属性来减少这种行为。我试过,它确实做了诀窍,但它并不完美。我仍然有一些颠簸(我必须设置为半径30px以获得正面效果)。

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

bump bug

使用illandril向我建议边缘技术(他只测试多边形 - 多边形接触)以避免圆圈在边缘崩溃:

slope edging technique

还尝试添加子弹选项,如Luc建议的那样,似乎没有任何改变。

此问题the demo 您可以尝试更改要检查的值:

  • 子弹选项
  • 边缘尺寸
  • 迭代计数
  • 物理学

(仅在最新的开发者Chrome上测试过)
保持耐心(或改变水平重力),你会明白我的意思 这里感兴趣的the repo

3 个答案:

答案 0 :(得分:2)

最好的解决方案是带有鬼顶点的边缘形状,但是如果你在使用的版本/端口中没有它,那么下一个最好的东西就像你的问题中的图表'edging',但是将多边形进一步扩展到地下斜率非常浅,如此线程:http://www.box2d.org/forum/viewtopic.php?f=8&t=7917

答案 1 :(得分:1)

我首先想到的问题可能来自两个相邻段之间斜率的变化,但是因为在多边形的平面上你仍然有凹凸,我认为问题是撞到多边形的角落。

我不知道你是否可以设置两组多边形,相互重叠?只需使用相同的插值计算并生成第二组多边形,就像下图所示:您已经构建了红色多边形集,并通过在红色多边形的中间设置绿色多边形的左顶点来添加绿色集,并且它的右顶点位于下一个红色多边形的中间。

![图] [1]

这应该适用于凹曲线......无论如何你应该飞过凸曲线。

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

- 编辑

在Box2D.js第5082行(至少在this repo中)你有PreSolve(接触,流形)功能,你可以覆盖它来检查歧管(碰撞多边形时雪球被冲击的方向) )是对的。

为此,您需要恢复流形矢量并将其与曲线的法线进行比较。它应该看起来像(可能不完全):

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 
};

答案 2 :(得分:0)

我说这个问题已在Box2D 2.2.0中得到解决,请参阅its manual, section 4.5 "Edge Shapes"

事物是it's a feature of the 2.2.0 version,连着chainhape的东西,而box2dweb实际上是从2.2.1a移植的 - 不知道box2dweb-closure。

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