最初は、隣接する 2 つのセグメント間の勾配の変化から問題が発生する可能性があると考えていましたが、ポリゴンの平らな表面にはまだ隆起があるため、問題はむしろポリゴンの角にぶつかっていると思います。
互いに重なり合う 2 つのポリゴン セットを設定できるかどうかわかりません。同じ補間計算を使用して、以下の図のようにポリゴンの 2 番目のセットを生成するだけです。赤のポリゴン セットを構築し、緑のポリゴンの左側の頂点を赤いポリゴンの中央に設定して緑のセットを追加します。次の赤いポリゴンの真ん中にある右の頂点。
![図][1]
これは凹状の曲線で機能するはずです...まあ、とにかく凸状のものの上を飛んでいるはずです。
これがうまくいかない場合は、多数のポリゴンを設定して斜面を構築してみてください。多角形の幅には、円の半径の 10 分の 1 を使用します。これにより、勾配の不連続が減少するはずです。
- 編集
Box2D.js の 5082 行目 (少なくともこのレポ内) には、マニホールド (ポリゴンが衝突したときに雪玉が衝撃を受ける方向) が正しいかどうかを確認するためにオーバーライドできる PreSolve(contact, manifest) 関数があります。
そのためには、マニホールド ベクトルを復元し、それをカーブの法線と比較する必要があります。そのように見えるはずです(正確ではないかもしれません):
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
};