斜壁与球的弹性碰撞

发布于 2024-07-10 03:00:16 字数 903 浏览 3 评论 0原文

我在计算球击中斜墙的反射角时遇到困难。 我正在使用从此教程中提取的算法。 它看起来像这样(在 Actionscript 3 中),其中 p1 是当前速度矢量,p2 是墙壁的法线:

private function getReflect2(p1 : Point, p2 : Point) : Point
{

    var wallvec : Point = getNorm(p2);
    var wallnorm  : Point = p2;

    var t : Number = dotProduct(wallvec, p1);
    var n : Number = dotProduct(wallnorm, p1);
    var vt : Point = new Point(wallvec.x * t, wallvec.y * t);
    var vn : Point = new Point(wallnorm.x * -n, wallnorm.y * -n);

    var vx : Number = dotProduct(new Point(1,0), vn) + dotProduct(new Point(1,0), vt);
    var vy : Number = dotProduct(new Point(0,1), vn) + dotProduct(new Point(0,1), vt);
    return new Point(vx, vy);
}

该函数返回新的速度矢量,并且对于与垂直墙壁的碰撞正确执行此操作,但对于倾斜墙壁则不然。 球可能会从两个“侧面”撞击墙壁(即法线可能会向另一个方向突出)。

有人能发现我的错误吗? 或者建议更好的算法?

I'm having trouble computing reflection angles for a ball hitting an oblique wall. I'm using an algorithm lifted from this tutorial. It looks like this (in Actionscript 3), with p1 being the current velocity vector and p2 the normal of the wall:

private function getReflect2(p1 : Point, p2 : Point) : Point
{

    var wallvec : Point = getNorm(p2);
    var wallnorm  : Point = p2;

    var t : Number = dotProduct(wallvec, p1);
    var n : Number = dotProduct(wallnorm, p1);
    var vt : Point = new Point(wallvec.x * t, wallvec.y * t);
    var vn : Point = new Point(wallnorm.x * -n, wallnorm.y * -n);

    var vx : Number = dotProduct(new Point(1,0), vn) + dotProduct(new Point(1,0), vt);
    var vy : Number = dotProduct(new Point(0,1), vn) + dotProduct(new Point(0,1), vt);
    return new Point(vx, vy);
}

The function returns the new velocity vector, and does so correctly for collisions with perpendicular walls but not for oblique ones. The ball may hit the wall from both "sides" (ie. the normal may be jutting in the other direction).

Can anyone spot my error? Or suggest a better algorithm?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

明天过后 2024-07-17 03:00:16

向量 wallvec 和 wallnorm 的量值必须为 1,函数才能正常工作。 我怀疑函数 getNorm() 为您处理 wallvec 的工作,但 wallnorm 似乎得到了任意大小。

此外,您的实现与页面上链接的算法不完全匹配。 特别是,该页面使用 P2 作为墙壁本身的方向。 然后,它对向量进行归一化(将幅度减小到 1,而不改变方向)并将其复制到 wallvec 中。 Wallnorm 接收墙的法线(其强度已经为 1)。

我的 C 实现如下所示。 请注意,即使 wnx 和 wny 与 p2c 和 p2y 方向相同,我仍然必须除以幅度。

void solve (double p1x, double p1y, double p2x, double p2y, double *p3x, double *p3y)
{
double wvx = -p2y / sqrt(p2x*p2x+p2y*p2y);
double wvy = p2x / sqrt(p2x*p2x+p2y*p2y);
double wnx= p2x/ sqrt(p2x*p2x+p2y*p2y);
double wny=  p2y/ sqrt(p2x*p2x+p2y*p2y);

double t = wvx*p1x+wvy*p1y;
double n = wnx*p1x+wny*p1y;

double vtx = wvx*t;
double vty = wvy*t;
double vnx = wnx*-n;
double vny = wny*-n;

*p3x=vnx+vtx;
*p3y=vny+vty;

}

Vectors wallvec and wallnorm must have a magnitude of 1 for the function to work. I suspect that the function getNorm() handles the work for wallvec for you, but wallnorm seems to get an arbitrary magnitude.

Also, your implementation doesn't exactly match the algorithm linked on the page. In particular, the page uses P2 as the direction of the wall itself. It then normalizes the vector (which reduces the magnitude to 1 without changing direction) and copies it into wallvec. Wallnorm receives the normal of the wall (which is already at magnitude 1.)

My C implementation looks like this. Note that even though wnx and wny is the same direction as p2c and p2y, I still had to divide by the magnitude.

void solve (double p1x, double p1y, double p2x, double p2y, double *p3x, double *p3y)
{
double wvx = -p2y / sqrt(p2x*p2x+p2y*p2y);
double wvy = p2x / sqrt(p2x*p2x+p2y*p2y);
double wnx= p2x/ sqrt(p2x*p2x+p2y*p2y);
double wny=  p2y/ sqrt(p2x*p2x+p2y*p2y);

double t = wvx*p1x+wvy*p1y;
double n = wnx*p1x+wny*p1y;

double vtx = wvx*t;
double vty = wvy*t;
double vnx = wnx*-n;
double vny = wny*-n;

*p3x=vnx+vtx;
*p3y=vny+vty;

}
很酷又爱笑 2024-07-17 03:00:16

我认为答案可能是关于“(即法线可能向另一个方向突出)”的部分。 如果法线指向“进入”墙壁,反射将穿过墙壁,而不是您期望的方向。

I think the answer may be the part about "(ie. the normal may be jutting in the other direction)." If the normal is pointed "into" the wall, the reflection will be through the wall, not in the direction you expect.

凡尘雨 2024-07-17 03:00:16

如果它适用于垂直,则可能 wallvec 不正确。 您是否打印了 wallvec 和其他值?

编辑:您能否提供当P1(1, 0)P2时的所有向量值>(0, 1)?

If it works for perpendicular, maybe wallvec is not right. Have you printed out wallvec and other values?

Edit: Could you provide all the vector values when P1 is (1, 0) and P2 is (0, 1)?

妥活 2024-07-17 03:00:16

这并不完全是您所问问题的答案,但最后几行不必要地复杂。 由于 (1, 0) 代表 x 轴,因此

dotProduct(new Point(1,0), vn)

可以用 vn.x 代替。 因此,通过简单地引用 vn 和 vt 的适当成员,函数的最后三行可以变得更加清晰:

return new Point(vn.x + vt.x, vn.y + vt.y);

我对 ActionScript 不太熟悉,不知道是否有更方便的方法来表达向量加法,但是直接表达向量加法会更好。

This isn't quite an answer to what you asked, but the last few lines are unnecessarily complicated. Since (1, 0) represents the x-axis,

dotProduct(new Point(1,0), vn)

can be replaced by vn.x. Thus, the last three lines of your function can be made a lot more clear by simply referring to the appropriate members of vn and vt:

return new Point(vn.x + vt.x, vn.y + vt.y);

I'm not familiar enough with ActionScript to know if there's a more convenient way to express vector addition, but it would be better to express the vector addition directly.

榕城若虚 2024-07-17 03:00:16

它未经测试,但这应该反映你的速度

private function reflectVectors(p1 : Point, p2 : Point) : Point
{
    // get the normalized normal
    var wallNorm:Point = p2.clone();
    wallNorm.normalize(1);

    // v1 = v - 2 * (v.n).n
    var dot:Number = p1.x * wallNorm.x + p1.y * wallNorm.y;
    var diff:Point = wallNorm.clone();
    diff.normalize(dot * -2);
    return p1.add(diff);
}

it's untested, but this should reflect your velocity

private function reflectVectors(p1 : Point, p2 : Point) : Point
{
    // get the normalized normal
    var wallNorm:Point = p2.clone();
    wallNorm.normalize(1);

    // v1 = v - 2 * (v.n).n
    var dot:Number = p1.x * wallNorm.x + p1.y * wallNorm.y;
    var diff:Point = wallNorm.clone();
    diff.normalize(dot * -2);
    return p1.add(diff);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文