Search code examples
javalibgdxbox2d

Assertion failed: (d + h * k > 1.19209290e-7F), function InitVelocityConstraints file ... b2MouseJoint.cpp, line 125


I'm using a MouseJoint to move bodies around in libgdx. It has been working fine with dynamic bodies, but with a certain kinematic body I get a weird error that makes the game crash. The error is:

Assertion failed: (d + h * k > 1.19209290e-7F), function InitVelocityConstraints, file /Users/badlogic/jenkins/workspace/libgdx-mac/extensions/gdx-box2d/gdx-box2d/jni/Box2D/Dynamics/Joints/b2MouseJoint.cpp, line 125.

Unfortunately, the stack is not shown upon crashing so I can't provide that. The error seems to be connected to the MouseJoint creation, but I did go step-by-step in debug and the creation itself goes by smoothly (or so it seems at least). Has anyone had the same error and survive to share his/her wisdom?

The code that creates the MouseJoint (which, as stated above, goes by fine. The game crashes elsewhere, I have no idea where) is:

mTmpMouseJointDef.bodyA = mWorld.createBody(mTmpBodyDef); // Create dummy body
mTmpMouseJointDef.bodyB = b_body;
mTmpMouseJointDef.collideConnected = true;
mTmpMouseJointDef.target.set(pTargetVec.x, pTargetVec.y);
mTmpMouseJointDef.maxForce = 1000.0f * b_body.getMass();
mouseJoint = (MouseJoint)mWorld.createJoint(mTmpMouseJointDef);

Solution

  • You simply can't use a MouseJoint with a kinematic body as bodyB, that's what is causing the assert (see this other SO post about the same problem).

    About the part from the Box2D manual you quote, it just states that in general, a joint between two bodies that are either kinematic or static can be created, but have no effect. However, this is not true with a MouseJoint, as it requires the bodyB mass to be non-zero (and in Box2D all kinematic and static bodies have zero mass).

    We can see that by looking at the code in the initVelocityConstraints function (from the JBox2D Github):

    public void initVelocityConstraints(final SolverData data) {
    
        // some code...
    
        float mass = m_bodyB.getMass();
    
        // Frequency
        float omega = 2.0f * MathUtils.PI * m_frequencyHz;
    
        // Damping coefficient
        float d = 2.0f * mass * m_dampingRatio * omega;
    
        // Spring stiffness
        float k = mass * (omega * omega);
    
        // magic formulas
        // gamma has units of inverse mass.
        // beta has units of inverse time.
        float h = data.step.dt;
        assert (d + h * k > Settings.EPSILON);
    
        // some code...
    
    }
    

    If mass is zero, then both the damping coefficient d and the spring stiffness k are zero, and d + h * k is zero, causing the assert.