Question

I've been trying to apply an angular impulse to a Body object in PlayN, but to no avail. Whichever value (radials) I enter, the angle of the body never changes. I have tried to set the torque as well with no results.

Example code that doesn't work:

BodyDef def = new BodyDef();
def.type = BodyType.DYNAMIC;
Body body = world.createBody(def);

float degToRad = (float) (180 / Math.PI);
float radials = (float) (50 / degToRad);

// None of the following options work.
body.applyAngularImpulse(radials);       // Immediate angular change.
body.applyTorque(radials);               // Angular change over time.

How can I get a valid body object to change its angle without manually setting its angular velocity (e.g. with setAngularVelocity)?

Thanks in advance!

I did notice that the torque and angular velocity are reset by calling the setWake method, which I never do manually, but it is invoked by the Island class:

public void setAwake(boolean flag) {
    ...
    m_angularVelocity = 0.0f;
    m_torque = 0.0f;
    ...
}

Note: Setting the angular velocity is not an option because I rely on the physics simulation. I've found an article for Box2D angle rotation, but it didn't change the outcome of the applyAngularImpulse method.

Was it helpful?

Solution

I've debugged some, and come to the conclusion the values that I've been using were way too low. When going through the applyAngularImpulse code I noticed a few things:

public void applyAngularImpulse(float impulse) {
    if (m_type != BodyType.DYNAMIC) {
        return;
    }

    if (isAwake() == false) {
        setAwake(true);
    }
    m_angularVelocity += m_invI * impulse;
}

m_invI is a really low value, something like 2.44882598E-4 so it makes sense if I use a too low value, that there is just no visible effect. If calculate the impulse from the question's example multiplied by the m_invI field:

m_invI                                 = 0.00044882598 = 2.449E-4
impulse          = 50 / 180 / PI       = 0.08841941282 = 8.842E-2
m_invI * impulse = 2.449E-4 * 8.842E-2 = 0.00002165237 = 2.165E-5 <--

That means just an angular velocity increment of 0.00002165237 per update cycle... Which is way too low to be noticeable it seems.

Also, while browsing the Box2D forums for similar situations, I found it there's a best practice to include the body's inertia into your angular impulse calculation. Like this:

body.applyAngularImpulse(speedValue * body.getInertia());

The inertia tends to be a high value (+4000) for me.

Hope this can be some help to others that have trouble applying an angular impulse or torque.

OTHER TIPS

In my case I forgot to call

body.setFixedRotation(false);

Even though I was setting mass, an inertia of 0 was reported and all torques and angular impulses were ignored.

Apparently it is fixed by default.

I had the same problem.

In my case I accidentally put my points in CW order (leading to negative area and zero mass). This was my incorrect code:

// incorrect version
triangleVertices.push(new B2Vec2(width / 2, 0.0)); // top
triangleVertices.push(new B2Vec2(0.0, height));    // left
triangleVertices.push(new B2Vec2(width, heightM)); // right

That looks like CCW, right? Nope, not in my coordinate system (+Y is down).

// corrected version
triangleVertices.push(new B2Vec2(width / 2, 0.0)); // top
triangleVertices.push(new B2Vec2(width, heightM)); // right
triangleVertices.push(new B2Vec2(0.0, height));    // left
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top