【问题标题】:How is my Rigid Body Collision code inconsistent?我的刚体碰撞代码如何不一致?
【发布时间】:2012-12-03 20:11:35
【问题描述】:

我一直在尝试复制此处找到的系统:http://www.myphysicslab.com/collision.html

到目前为止,这是我的代码(针对撞击无限大物体的情况,例如不可移动的墙):

public static Orientation collide( float bodyMass_1, float bodyVelocityX_1, float bodyVelocityY_1, float bodyAngleMomentum_1 , float pointXFromCenterX_1, 
float pointYFromCenterY_1, float momentOfInertia_1,
float edgeNormalX, float edgeNormalY, float elasticity )
{
    Orientation returning;

    float outAngleMomentum_1;

    float outVelocityX_1, outVelocityY_1;

    float relativeNormal;
    float deltaParameter;

    float pointVelocityX_1, pointVelocityY_1;

    pointVelocityX_1 = bodyVelocityX_1 - bodyAngleMomentum_1 * pointYFromCenterY_1;
    pointVelocityY_1 = bodyVelocityY_1 + bodyAngleMomentum_1 * pointXFromCenterX_1;


    System.out.println( edgeNormalX );
    System.out.println( edgeNormalY );

    relativeNormal = (float) Funct3D.dotProduct( pointVelocityX_1, pointVelocityY_1,edgeNormalX, edgeNormalY );


    if ( relativeNormal < 0 )
    {

        deltaParameter = (-(1 + elasticity) *( (float) Funct3D.dotProduct( pointVelocityX_1, pointVelocityY_1, edgeNormalX, edgeNormalY ) ))/ 
        ( 1/bodyMass_1 + Funct3D.sqr( (float) Funct3D.perpDotProduct(pointXFromCenterX_1,pointYFromCenterY_1,edgeNormalX,edgeNormalY)) / momentOfInertia_1 );

        outVelocityX_1 = bodyVelocityX_1 + deltaParameter * edgeNormalX / bodyMass_1;
        outVelocityY_1 = bodyVelocityY_1 + deltaParameter * edgeNormalY / bodyMass_1;

        outAngleMomentum_1 = bodyAngleMomentum_1 + (float)     Funct3D.perpDotProduct(pointXFromCenterX_1, pointYFromCenterY_1,     deltaParameter*edgeNormalX, deltaParameter*edgeNormalY ) / momentOfInertia_1;

        returning = new Orientation( outVelocityX_1, outVelocityY_1, outAngleMomentum_1 );
    }
    else
    {
        System.out.println( "NO COLLISION" );
        returning = new Orientation( bodyVelocityX_1, bodyVelocityY_1, bodyAngleMomentum_1 );
    }
    return returning;
}

我的代码的结果通常导致速度不能通过法线反映,或者完全缺乏动量守恒。即使我有它只是让它在执行后立即输出结果,结果表明它不是多次注册碰撞的问题,它也会在第一次运行时发生。

dotProduct 返回两个向量的点积。

perpDotProduct 返回两个向量的点积

如果您需要任何解释,或者如果您想请求扩大代码范围,请随时提出。

【问题讨论】:

  • 可能与您的问题无关,但是:“清洁代码”建议方法的参数不要超过 3 个,并认为更多的参数会浪费封装的机会。想象一下您的代码读取它有多简单,您将坐标对/向量封装到它们自己的类中,该类还提供添加、缩放和计算所涉及向量的点积的操作。
  • 如果您的程序输出错误,您应该考虑使用调试器来尝试发现问题。见stackoverflow.com/questions/25385173/…

标签: java physics collision rigid-bodies


【解决方案1】:

对于这类任务,我建议编写一个简单的测试,将输入参数传递给 collide 方法,并期望 Orientation 具有已知有效的值。

你可以使用JUnit框架或者简单的main方法:

Orientation orientation = collide(a, b, c, d, ...);
assertEquals(KNOWN_X, orientation.getX());
assertEquals(KNOWN_Y, orientation.getX());
assertEquals(KNOWN_MOMENTUM, orientation.getMomentum());

使用此代码,您可以调试您的方法并检查算法每一步的值是否正确。然后您可以使用一组新的已知输入和输出值检查算法。

还可以考虑清理代码并将重复计算移至局部变量(即deltaParameter * edgeNormalX

【讨论】:

  • 我实际上已经考虑过这样做,但我找不到任何测试用例,除非假设 x 速度为 0,并且在没有旋转的情况下向下移动,如果它达到水平墙它应该只是垂直反弹。您是否知道或可以提供一个系统来生成一组案例?是的,它有点肮脏和支离破碎。我正在考虑结合速度和碰撞向量之间的所有点积,但我最近一直在改变它,试图测试不同的替代方案,我认为最好让它保持原样,但当我完成时我会这样做。
  • 嗯,这是一个非常具体的问题,我不是物理学家。我在这方面的知识仅限于我们在大学的课程,那是很久以前的事了。如果您知道代码有问题,那么您应该有一份应该是正确的纸上计算。也就是说,将您的论文计算与您的代码所做的比较。
  • 好吧,经过几个测试用例和辛苦工作——我找到了问题所在。这是我的段到段拦截方法中的一个特殊情况,它把它扔掉了。显然,由于变量命名错误,它会在一定范围内抛出不稳定的数字。感谢 Hoaz,它已得到修复,我将努力减少冗余计算并将参数分类在一起。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多