Box2D Java

Discuss issues specific the Java port of Box2D
toucansam
Posts: 356
Joined: Mon Jun 08, 2009 12:21 pm
Contact:

Re: Box2D Java

Postby toucansam » Mon Jun 15, 2009 10:27 pm

I noticed that the getManifolds() method in all of the contacts was returning a brand new ArrayList every time, and now that our manifold instance doesn't change (thanks to it's brand new set method), I create and populate an arraylist at construction and just return that.

Edit: Also, how different is the regular Box2D from the java version?

Edit numba 2: I'm starting to upgrade to box2d build 218. just did the math library

toucansam
Posts: 356
Joined: Mon Jun 08, 2009 12:21 pm
Contact:

Re: Box2D Java

Postby toucansam » Sun Jun 21, 2009 9:52 am

Ok so scratch that, we're going to hold on updating the engine. Right now I'm doing a second pass of optimizations (its running even faster now), and adding documentation (we should see a new release soon, and then we'll begin to update it). Ewjordan's going to try and split off a catagory in the forums for VM ports, and have a forum specifically for jbox2d. That way it won't get so confusing all in one thread. Also, we're going to probably put a small wordpress blog on jbox2d.org, so people can sign up for notifications on updates, etc.

Edge
Posts: 70
Joined: Tue Nov 18, 2008 6:46 pm

Re: Box2D Java

Postby Edge » Mon Jun 22, 2009 3:02 pm

Keep up the good work. I like where this is going :D

While you're plugging away in there, was wondering if you could explain this. From Island.solve(), seems like all this cares about is the minSleepTime from the last dynamic body, but it loops through all of them to get at it. In most cases that doesn't seem like a big deal as most islands only have 1-2 bodies, but some occasionally get into the 170+ range. Can we break out of the loop when we set min to 0.0f in a couple places?

Code: Select all

      if (allowSleep) {
         float minSleepTime = Float.MAX_VALUE;

         final float linTolSqr = Settings.linearSleepTolerance * Settings.linearSleepTolerance;
         final float angTolSqr = Settings.angularSleepTolerance * Settings.angularSleepTolerance;

         for (int i = 0; i < m_bodyCount; ++i) {
            final Body b = m_bodies[i];
            if (b.m_invMass == 0.0f) {
               continue;
            }

            if ((b.m_flags & Body.e_allowSleepFlag) == 0) {
               b.m_sleepTime = 0.0f;
               minSleepTime = 0.0f;
            }

            if ((b.m_flags & Body.e_allowSleepFlag) == 0 ||
                  b.m_angularVelocity * b.m_angularVelocity > angTolSqr ||
                  Vec2.dot(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr) {
               b.m_sleepTime = 0.0f;
               minSleepTime = 0.0f;
            } else {
               b.m_sleepTime += step.dt;
               minSleepTime = MathUtils.min(minSleepTime, b.m_sleepTime);
            }
         }

         if (minSleepTime >= Settings.timeToSleep) {
            for (int i = 0; i < m_bodyCount; ++i) {
               final Body b = m_bodies[i];
               b.m_flags |= Body.e_sleepFlag;
               b.m_linearVelocity = new Vec2(0.0f, 0.0f);
               b.m_angularVelocity = 0.0f;
            }
         }
      }


Also, how much do the bitflags speed things up? Are they worth keeping (can be a pain to work with)? Lot of other duplicated code in Body as well (ex. set mass logic as a separate method and in the constructor).

toucansam
Posts: 356
Joined: Mon Jun 08, 2009 12:21 pm
Contact:

Re: Box2D Java

Postby toucansam » Mon Jun 22, 2009 10:54 pm

Edge wrote:Keep up the good work. I like where this is going :D

Thanks!

Edge wrote:While you're plugging away in there, was wondering if you could explain this. From Island.solve(), seems like all this cares about is the minSleepTime from the last dynamic body, but it loops through all of them to get at it. In most cases that doesn't seem like a big deal as most islands only have 1-2 bodies, but some occasionally get into the 170+ range. Can we break out of the loop when we set min to 0.0f in a couple places?

Code: Select all

      [snip]
           if ((b.m_flags & Body.e_allowSleepFlag) == 0) {
               b.m_sleepTime = 0.0f;
               minSleepTime = 0.0f;
            }

            if ((b.m_flags & Body.e_allowSleepFlag) == 0 ||
                  b.m_angularVelocity * b.m_angularVelocity > angTolSqr ||
                  Vec2.dot(b.m_linearVelocity, b.m_linearVelocity) > linTolSqr) {
               b.m_sleepTime = 0.0f;
               minSleepTime = 0.0f;
            } else {
               b.m_sleepTime += step.dt;
               minSleepTime = MathUtils.min(minSleepTime, b.m_sleepTime);
            }
         }

      if (minSleepTime >= Settings.timeToSleep) {
            for (int i = 0; i < m_bodyCount; ++i) {
               final Body b = m_bodies[i];
               b.m_flags |= Body.e_sleepFlag;
               b.m_linearVelocity = new Vec2(0.0f, 0.0f); // gotcha!
               b.m_angularVelocity = 0.0f;
            }
         }
      }
         [snip]


I see what you're saying, but the only thing I notice is that the sleep time of each body is incremented in that last else statement. So it's purpose isn't only to find the minSleepTime, it also increments the time an object has been "sleeping", even if the group isn't. That way, when the "active" object leaves, the "sleeping" object can populate that minSleepTime field with it's sleeping time. But I think we can remove two things here, that middle if statement (the one at the top of the snip), and I also see where I can eliminate a Vec2 creation :D can't believe I missed that.

Edge wrote:Also, how much do the bitflags speed things up? Are they worth keeping (can be a pain to work with)? Lot of other duplicated code in Body as well (ex. set mass logic as a separate method and in the constructor).

I'm not really sure, but they're easy to work with, and removing them will be a hassle, especially when we start updating the engine. Also, in my optimizations, I've generally tried to not change anything structurally, as I'm not recreating the engine, I'm just optimizing what's there. I would only bother about any structural changes after ewjordan and I have fully updated the engine to the current box2d build, as I'm sure Erin's made optimizations too (I think we're based around build 142, and box2d is on 210, and from what I've seen a lot has changed).

But thanks for looking into it, and I'll definitely take out that if statement and remove that creation. And if I didn't quite understand what you were suggesting, please elaborate, as I can miss things.

Edge
Posts: 70
Joined: Tue Nov 18, 2008 6:46 pm

Re: Box2D Java

Postby Edge » Tue Jun 23, 2009 6:55 am

You're right, I overlooked the part about incrementing the body's sleep time. Glad to see some improvements still came out of this though.

For the bit flags, they aren't too bad once I consult my cheatsheet (is that setting to true or false?). Just not very Java like I guess and from everything I've read bitflags don't really speed performance up in Java. I agree with not changing them until we get the latest Box2D changes though. Will the porting of that start soon?

mh114
Posts: 20
Joined: Thu Jul 03, 2008 7:58 am
Location: Finland
Contact:

Re: Box2D Java

Postby mh114 » Tue Jun 23, 2009 7:31 am

Awesome job optimizing, the Vec2 creations are much much lower than what they used to be! Keep up the good work guys! :)

I have a patch here, you can add it if you'd like; the changes are mainly to allow my level parsing code to use the convex decomposition features. I also removed the LiquidTest reference from World/DebugDraw, as the LiquidTest is not included in the library jar, it naturally crashes when I enable debug draw. I've also removed a couple of @Override-annotations, Java 5 doesn't allow them in interfaces (as implementing is not overriding, this has been changed for Java 6 though).

Code: Select all

Index: org/jbox2d/dynamics/ContactManager.java
===================================================================
--- org/jbox2d/dynamics/ContactManager.java   (revision 169)
+++ org/jbox2d/dynamics/ContactManager.java   (working copy)
@@ -52,7 +52,6 @@
       m_destroyImmediate = false;
    }

-   @Override
    public Object pairAdded(final Object proxyUserData1, final Object proxyUserData2) {
       Shape shape1 = (Shape) proxyUserData1;
       Shape shape2 = (Shape) proxyUserData2;

@@ -127,7 +126,6 @@
     // This is a callback from the broadphase when two AABB proxies cease
    // to overlap. We retire the b2Contact.
-   @Override
    public void pairRemoved(final Object proxyUserData1, final Object proxyUserData2,
                            final Object pairUserData) {
       //B2_NOT_USED(proxyUserData1);

Index: org/jbox2d/dynamics/World.java
===================================================================
--- org/jbox2d/dynamics/World.java   (revision 169)
+++ org/jbox2d/dynamics/World.java   (working copy)
@@ -51,7 +51,6 @@
 import org.jbox2d.dynamics.joints.JointEdge;
 import org.jbox2d.dynamics.joints.JointType;
 import org.jbox2d.dynamics.joints.PulleyJoint;
-import org.jbox2d.testbed.tests.LiquidTest;
 
@@ -1009,7 +1008,7 @@
           circCenterMoved.x = drawingCenter.x + .01f;
          circCenterMoved.y = drawingCenter.y + .01f;
-         if (circle.getUserData() != null && circle.getUserData() == LiquidTest.LIQUID_INT) {
+         if (circle.getUserData() != null) {
             m_debugDraw.drawSegment(drawingCenter, circCenterMoved, liquidColor);
             return;
          }
Index: org/jbox2d/util/nonconvex/Polygon.java
===================================================================
--- org/jbox2d/util/nonconvex/Polygon.java   (revision 169)
+++ org/jbox2d/util/nonconvex/Polygon.java   (working copy)
@@ -430,7 +430,7 @@
        *
        * For internal use.
         */
-   private Polygon add(Triangle t) {
+   public Polygon add(Triangle t) {
 //         float equalTol = .001f;
            // First, find vertices that connect
            int firstP = -1;
Index: org/jbox2d/util/nonconvex/Triangle.java
===================================================================
--- org/jbox2d/util/nonconvex/Triangle.java   (revision 169)
+++ org/jbox2d/util/nonconvex/Triangle.java   (working copy)
@@ -1,6 +1,6 @@
 package org.jbox2d.util.nonconvex;
 
-class Triangle{
+public class Triangle {
     
     public float[] x;
     public float[] y;

toucansam
Posts: 356
Joined: Mon Jun 08, 2009 12:21 pm
Contact:

Re: Box2D Java

Postby toucansam » Tue Jun 23, 2009 11:12 am

Great, thanks, I've incorporated those. I do have some bad news, it seems as though I have broke something, if you look at the pyramid and domino stress tests, they kinda collapse. So I'll have to go back through the revisions and see what i did :cry: which is a bit tedious.

but thank god for version control

Edit: it seems as though I broke it in rev 167, as 166 is fine.

Edit 2: we're good, i found the problem. I had set() a manifold in ContactSolver, when instead it needed to be a direct object reference.

toucansam
Posts: 356
Joined: Mon Jun 08, 2009 12:21 pm
Contact:

Re: Box2D Java

Postby toucansam » Tue Jun 23, 2009 2:44 pm

Edge wrote:I agree with not changing them until we get the latest Box2D changes though. Will the porting of that start soon?


It will start as soon as we make a release. The only thing left to do is include raycasting, which ewjordan was going to do. He's a bit busy though, so I might try to put them in, but the only places that mention it in the source are Segment and PolygonShape, and I'm not sure if it is in more places in the engine. I'll have to grab rev 142 of Box2D to see if it's anywhere else in the engine.

Edit: I found what needs to be added, and I'm in the process of adding raycasting

Edit 2: I finished adding raycasting to the shapes, and I think that build 172 is going to be the next release. I'm now going to start updating the engine, which hopefully won't take too long

Edge
Posts: 70
Joined: Tue Nov 18, 2008 6:46 pm

Re: Box2D Java

Postby Edge » Tue Jun 23, 2009 8:26 pm

Good deal.

Hmm... somewhere between 169 and 172 the rendering of circles broke for my apps. They still act as they always did with respect to other shapes/bodies in the simulation, but are drawn as really tiny dots. However, they seem to render fine in the other testbed apps (except I noticed the sensor outlines are gone in the sensor test). Here is my code to create a circle (all my cases use the parent == null path). What am I doing that should have changed?

Code: Select all

 Removed to keep the post short, see findings below


Edit: Has something to do with setting userData on the shapedef. When I comment out that line it works. Even if I set it on the resulting shape (m_userData) instead of the shape def it causes the problem.

Edit2: Found it. In World.drawShape, there is code that assumes if userData is non-null that it must be the LiquidTest app. I assume this is mh114's change.

Code: Select all

         if (circle.getUserData() != null) {
            m_debugDraw.drawSegment(drawingCenter, circCenterMoved, liquidColor);
            return;
         }

mh114
Posts: 20
Joined: Thu Jul 03, 2008 7:58 am
Location: Finland
Contact:

Re: Box2D Java

Postby mh114 » Tue Jun 23, 2009 9:58 pm

Edge wrote:Edit2: Found it. In World.drawShape, there is code that assumes if userData is non-null that it must be the LiquidTest app. I assume this is mh114's change.

Code: Select all

         if (circle.getUserData() != null) {
            m_debugDraw.drawSegment(drawingCenter, circCenterMoved, liquidColor);
            return;
         }
Oops, so sorry about that! Now this is embarassing, I don't currently have any circles in my game project (apart from circle sensors) so I didn't spot that.. :oops: I think that whole if-statement will need to go, as it's for the liquids -- and I don't see the reason to keep the dependency as LiquidTest is not included in the lib anyway..

Sorry again, you should remove that if and it should work again.. :)


Return to “Java”



Who is online

Users browsing this forum: No registered users and 1 guest