WeldJoint Anchor position for colliding bodies

Discuss issues specific the Java port of Box2D
Divereth
Posts: 5
Joined: Sun Jun 08, 2014 3:12 am

WeldJoint Anchor position for colliding bodies

Postby Divereth » Thu Jul 31, 2014 3:24 pm

Hi, I want to join dynamic bodies with WeldJoint when they collide with each other.
I managed to do that with the use of ContactListener. I take the bodies from PreSolve (I don't want the impact to influence the bodies) and Weld them right after world.step.
Joint is created, but I cannot get them to be welded in the right position (the one they connected in).

I tried all the logical formulas I could think of, and some dumb ones as well. getLocalPoints, getWorldPoints and even something with manifold, but I couldn't achieve the right outcome.

Help?

relevant part of the code
ContactListener:

Code: Select all

private Array<Body> weldsToMake;
private Array<Vector2> positionWeld;

public void preSolve(Contact c, Manifold m) {
      Fixture fa = c.getFixtureA();
      Fixture fb = c.getFixtureB();

      if(fa.getUserData() != null
            && fa.getUserData().equals("animal")
            && fb.getUserData().equals("platform")) {

         weldsToMake.add(fb.getBody()); //platform
         weldsToMake.add(fa.getBody()); //animal   
      }
      if(fb.getUserData() != null && fa.getUserData() != null
            && fb.getUserData().equals("animal")
            && fa.getUserData().equals("platform")) {
         weldsToMake.add(fa.getBody()); //platform
         weldsToMake.add(fb.getBody()); //animal
      }
   }
   

Play screen:

Code: Select all

public void WeldAnimals() {
      //weld box to scale
      for(int i = 1; i < cl.getWelds().size / 2; i++){
         
      WeldJointDef jdef = new WeldJointDef();
      jdef.collideConnected = false;
      
      Vector2 worldAnchorPoint = cl.getWelds().peek().getWorldPoint(new Vector2(0, -1));
      
      jdef.bodyA = cl.getWelds().pop();
      jdef.bodyB = cl.getWelds().pop();
      jdef.localAnchorA.set(jdef.bodyA.getLocalPoint(worldAnchorPoint));
      jdef.localAnchorB.set(jdef.bodyB.getLocalPoint(worldAnchorPoint));
   
      world.createJoint(jdef);
      }
   }

irresistible force
Posts: 1991
Joined: Tue Jun 24, 2008 8:25 pm
Location: Tokyo
Contact:

Re: WeldJoint Anchor position for colliding bodies

Postby irresistible force » Thu Jul 31, 2014 5:45 pm

It's kinda hard to give any opinion without knowing what getWelds and peek return?
Where does the location (0,-1) come from?
I would think that using the manifold is the only what you can do this. These might be helpful:
http://www.iforce2d.net/b2dtut/collision-anatomy
http://www.iforce2d.net/b2dtut/sticky-projectiles

Divereth
Posts: 5
Joined: Sun Jun 08, 2014 3:12 am

Re: WeldJoint Anchor position for colliding bodies

Postby Divereth » Fri Aug 01, 2014 10:27 am

Code: Select all

public Array<Body> getWelds() { return weldsToMake; }
   public Array<Vector2> getPositions() { return positionWeld; }

sorry

Thanks for reply.
I read the "Sticky projectiles tutorial" already and tried to copy the code to java (but the positions were still off). And I don't know C++ so I don't understand all the code well (i.e. StickyInfo& si?)

(0,-1) is the local coordinate of the bottom animal's box. (It is supposed to stick on top of the 'platform' box). It's just a temporary value for know until I figure out how to make this all work properly.
I'll study the first link now and fight with the problem again.
If anyone has some ideas please share. Thanks

Divereth
Posts: 5
Joined: Sun Jun 08, 2014 3:12 am

Re: WeldJoint Anchor position for colliding bodies

Postby Divereth » Fri Aug 01, 2014 10:59 am

Ok, It somehow works now :) WorldManifold from beginContact is the answer.

Code: Select all

public void beginContact(Contact contact) {
      WorldManifold manifold;
      manifold = contact.getWorldManifold();
      
      for(int i = 0; i < manifold.getNumberOfContactPoints(); i++)
      {
         positionWeld.add(new Vector2(manifold.getPoints()[i].x, manifold.getPoints()[i].y));
      }
   }
   

Code: Select all

      jdef.bodyA = cl.getWelds().pop();
      jdef.bodyB = cl.getWelds().pop();
      jdef.localAnchorA.set(jdef.bodyA.getLocalPoint(cl.getPositions().peek()));
      jdef.localAnchorB.set(jdef.bodyB.getLocalPoint(cl.getPositions().pop()));


When the bodies fall directly flat on the platform they are welded nicely, but when they are rotated it's still not accurate, but it's a major progress :)
edit: resolved that as well.


EDIT: another problem emerged: When I weld ~17 boxes to the platform the whole thing is getting epileptic and bounces around, even though I have set jdef.collideConnected = false; and the welded bodies don't connect with each other (bit filtering). Any ideas? Is Box2D panicing since it has to calculate a body with 20 other bodies attached to it?
I do not get any fps drops. Just jiggling.
edit2: increasing the step iterations helped a bit. Now it starts to jiggle when 20 bodies are attached instead of 15.

irresistible force
Posts: 1991
Joined: Tue Jun 24, 2008 8:25 pm
Location: Tokyo
Contact:

Re: WeldJoint Anchor position for colliding bodies

Postby irresistible force » Fri Aug 01, 2014 4:22 pm

Weld joints are ok for making soft connections, but they are not very good for making a completely solid join between two bodies.
If you want a 100% rigid join, you will have to make the two bodies become one body (that is, put the fixtures from one body onto the other, then destroy the body they came from). You can see an example of that on the sticky projectiles page as well.


Return to “Java”



Who is online

Users browsing this forum: Google [Bot] and 1 guest