new phys2d joint

Hi everybody,

I believe this is my first post here, so a quick introduction. My name is Gideon, I’m a 6th year cs student (last year of my master) in the Netherlands. Currently I’ve started working on an old project I started a few years ago called towship (http://towship.sourceforge.net/). It needs a good physics system, but building one myself proved too difficult. I tried two other libraries before running into phys2d a few weeks ago, which seems to be good enough (provided that it will have polygon support sometime).

For my little game I needed a different kind of joint that could model a rope (or actually a grappler). Of course a chain of phys2d BasicJoint’s could’ve done the trick but that turned out to be rather unstable. The new joint represents a spring that can have different spring constants for compression and stretching, furthermore it can have a maximum and minimum length.

I finished this code only yesterday, so it hasn’t been thoroughly debugged (quite the contrary), however I’m posting it anyway because I have a few questions that some of you might be able to answer. First of all, I don’t understand the so called ‘clamping’ that Erin Catto uses to achieve greater accuracy or if it would help in for this joint. Secondly I have no idea how the massNormal (which in the BasicJoint is represented by a matrix) works, maybe someone could point me to some more information on those subjects?

Anyways, hopefully this code will be useful to anyone. Attached is the SpringJoint source code and a Demo that tests it.

– gideon

Hey Gideon,

I have to admit to porting most of the code from Eric Catto without understand how the maths worked. You’d probably be best to post the questions at http://www.continuousphysics.com/Bullet/phpBB2/index.php which is where I got help when building the java version of the code.

I thought the interest in Phys2D had died out but it seems theres a few people in the last weeks who have got interested and found issues.

Thanks for the source, I’m currently without internet access at home but I’ll check it out asap and get it in the code base if it’s all working (assuming that was your intention?).

Re: Polygon support - CK was working on this but I’m not sure what the state is - was bugged last time I heard.

Can’t wait to check the game out :slight_smile:

Kev

Thanks for the link. I know work is being/was done on polygon support, I’ve had a look at the code but it was a bit too messy for me, the code that is (sorry cmdr keith ;)). I might start working on the implementation myself if the need arises, for now I’m concentrating on different issues.

If you find the joint useful please do integrate it with the other code (under the BSD license like the rest). By the way, it would be quite simple to write a more (at least twice as) efficient FixedJoint (or so I believe), but I don’t need it personaly. Do you think it’s worth the effort?

–gideon

Right now I’ve no idea if there are enough users of Phys2D to warrant adding features that no one actually requires yet - so I’d hold off. If of course you do end up need a performance boost and write it I’d be happy to integrate that too! :slight_smile:

I’m considering trying to push the project a little more especially now people are talking about an API that brings 2D entity management with Slick + Phys2D together.

Kev

If that happens and gets done, I’m switching Stencyl over to Slick in a jiffy. :slight_smile:

  • Eliwood

The SpringJoint sounds like it is just what I need for a particular task. What I would like to set up is two or more bodies essentially connected with a SpringJoint. One of the bodies would have a force applied to it to give the system some movement, thus causing all the attached bodies to move along with it because of the joint(s). I expect this would give sort of a flimsy, bouncy look and feel (especially on collision). Flimsy is probably not the exact word I should use there, but I hope the idea is coming across OK.

The idea here is to create a body that would mimic a non-rigid body. I think this would add some new possibilities to what Phys2D is capable of simulating.

I didn’t find a good example of how to use any of the joints to support what I am trying to do. Any help? Thanks.

The best way to get some experience is to fiddle with the examples. Demo21 shows the SpringJoint. Using the SpringJoint to simulate non-rigid body simulation might work, but I suspect it will not give very nice results. For example the SpringJoint tends to be quite bouncy as it has no built-in friction. I’m quite sure the SpringJoint is too simple to be used for general non-rigid body simulation, but maybe it could be used in some cases.

Did you have a specific application in mind?

I admit, my attempts to get the joint to work were perhaps half behinded (if you know what I mean). I will work at getting something working and report back.

The application I have in mind might be something like a tree and when hit, all the leaves would shake around with a nice physics look. I am sure the same effect (or close enough) could be accomplished through sprite animation since we are talking about 2D graphics here, but I would still like to check it out for myself.

A tree is not the only example application. It could apply to some blob of a character that has a jiggly stomach that things can hit and bounce off of. I think something like that would have a real nice look to it.

So, I will see what I can come up with. Thanks for any help/guidance.

Here is some code. Not exactly were I want to go with this, but it might be nice to look at to get a general idea…maybe spark something in someone.

package net.phys2d.raw.test;

import net.phys2d.math.Vector2f;
import net.phys2d.raw.Body;
import net.phys2d.raw.SpringJoint;
import net.phys2d.raw.StaticBody;
import net.phys2d.raw.World;
import net.phys2d.raw.shapes.Box;

/**
 * Another Demo for the spring joint.
 * This should demonstrate how a non-rigid body could be simulated.
 * There are some special keys for moving the body around.
 * 	w - up
 *  s - down
 *  a - left
 *  d - right
 *  space - jump (just press it and let go, or else it will continue to jump!!!  maybe thats kinda fun though)
 * 
 * @author Shaun Sheppard
 */
public class Demo21_Extension extends AbstractDemo {
	
	float RADIUS = 100f;
	float DIAMETER = RADIUS * 2;
	Vector2f tmpForce = new Vector2f();
	float MOVE_FORCE = 15000f;
	/** Ensure this is nicely divisible by 2 (even). This is the number of bodies created around the center body. */
	int OUTER_BODY_COUNT = 12;

	Body ground = new StaticBody("ground", new Box(500.0f, 20.0f));
	Body centerBody = new Body("centerBody", new Box(10.0f, 10.0f), 10.0f);


	/**
	 * Create the demo
	 */
	public Demo21_Extension() {
		super("Demo 21_Extension: A Non-Rigid Body (using SpringJoints)");
	}
	
	/**
	 * @see net.phys2d.raw.test.AbstractDemo#init(net.phys2d.raw.World)
	 */
	protected void init(World world) {
		ground.setPosition(250.0f, 450);
		world.add(ground);
		
		centerBody.setPosition(250f, 100f);
		world.add(centerBody);
		
		double radiansBetweenOuterBodies = Math.PI * 2 / OUTER_BODY_COUNT;
		double currentRadians = 0;
		Body[] outerBodies = new Body[OUTER_BODY_COUNT];
		int i;
		float distanceBetweenOuterBodies = 0f;
		for (i = 0; i < OUTER_BODY_COUNT; ++i) {
			// First create the body
			outerBodies[i] = new Body("outerBody-" + i, new Box(20f, 20f), 50f);
			outerBodies[i].setFriction(1f); // high friction to have them grip the ground like a tire.
			double x = Math.sin(currentRadians) * RADIUS;
			double y = Math.cos(currentRadians) * -RADIUS;
			outerBodies[i].setPosition((float)x + centerBody.getPosition().getX(), (float)y + centerBody.getPosition().getY());
			world.add(outerBodies[i]);
			
			// Then add the spring joint back to the centerBody
			SpringJoint jointToCenter = new SpringJoint(outerBodies[i], centerBody, outerBodies[i].getPosition(), centerBody.getPosition());
			jointToCenter.setBrokenSpringConst(1);
			jointToCenter.setCompressedSpringConst(0f);
			jointToCenter.setStretchedSpringConst(0f);
			jointToCenter.setSpringSize(RADIUS);
			jointToCenter.setMinSpringSize(RADIUS * 0.99f);
			jointToCenter.setMaxSpringSize(RADIUS * 1.01f);
			world.add(jointToCenter);
			
			if (i > 0) {
				// Then add the joint to hold the outer bodies together to hold some form
				SpringJoint jointToPreviousOuterBody = new SpringJoint(outerBodies[i], outerBodies[i - 1], outerBodies[i].getPosition(), outerBodies[i - 1].getPosition());
				jointToPreviousOuterBody.setBrokenSpringConst(1);
				jointToPreviousOuterBody.setCompressedSpringConst(0f);
				jointToPreviousOuterBody.setStretchedSpringConst(0f);
				if (distanceBetweenOuterBodies == 0f) { // Only do this calculation once...
					float sideA = outerBodies[i].getPosition().getX() - outerBodies[i - 1].getPosition().getX();
					float sideB = outerBodies[i].getPosition().getY() - outerBodies[i - 1].getPosition().getY();
					distanceBetweenOuterBodies = (float)Math.sqrt((sideA * sideA) + (sideB * sideB));
				}
				jointToPreviousOuterBody.setSpringSize(distanceBetweenOuterBodies);
				jointToPreviousOuterBody.setMinSpringSize(distanceBetweenOuterBodies * 0.9f);
				jointToPreviousOuterBody.setMaxSpringSize(distanceBetweenOuterBodies * 1.1f);
				world.add(jointToPreviousOuterBody);
			}
			
			currentRadians += radiansBetweenOuterBodies;
		}
		
		// Dont forget, the way we did this requires to add this one last joint
		--i;
		SpringJoint jointToPreviousOuterBody = new SpringJoint(outerBodies[i], outerBodies[0], outerBodies[i].getPosition(), outerBodies[0].getPosition());
		jointToPreviousOuterBody.setBrokenSpringConst(1);
		jointToPreviousOuterBody.setCompressedSpringConst(0f);
		jointToPreviousOuterBody.setStretchedSpringConst(0f);
		jointToPreviousOuterBody.setSpringSize(distanceBetweenOuterBodies);
		jointToPreviousOuterBody.setMinSpringSize(distanceBetweenOuterBodies * 0.9f);
		jointToPreviousOuterBody.setMaxSpringSize(distanceBetweenOuterBodies * 1.1f);
		world.add(jointToPreviousOuterBody);
	}
	
	/*
	 * (non-Javadoc)
	 * @see net.phys2d.raw.test.AbstractDemo#keyHit(char)
	 */
	protected void keyHit(char c) {
		super.keyHit(c);
		if (c == 'w') {
			tmpForce.set(0, -MOVE_FORCE);
			centerBody.addForce(tmpForce);
		} else if (c == 's') {
			tmpForce.set(0, MOVE_FORCE);
			centerBody.addForce(tmpForce);
		}
		if (c == 'a') {
			tmpForce.set(-MOVE_FORCE, 0);
			centerBody.addForce(tmpForce);
		} else if (c == 'd') {
			tmpForce.set(MOVE_FORCE, 0);
			centerBody.addForce(tmpForce);
		}
		if (c == ' ') {
			tmpForce.set(0, -MOVE_FORCE * 100);
			centerBody.addForce(tmpForce);
		}
	}
	
	/**
	 * Entry point for tetsing
	 * 
	 * @param argv The arguments to the test
	 */
	public static void main(String[] argv) {
		Demo21_Extension demo = new Demo21_Extension();
		demo.start();
	}

}

In my opinion your demo also shows some of the limitations of this approach:

  • configuring the behaviour of the ‘blob’ is difficult, i.e. not intuitive
  • a large number of joints is required, which is very expensive to calculate and with the current method gets more inaccurate if there are more connected joints
  • what about non-convex or even non-star-shaped bodies, where should the joints be placed? An arbitrary triangulation with joints might do it, but it wouldn’t be nice to have
    different behaviour for different triangualtions.

I guess what I’m trying to say is that, altough the SpringJoint can be used as you do for deforming objects for specific cases. But using it to implement general deforming colliders would not be a good idea in my opinion.

By the way you seem to have misinterpreted the control parameters of the spring joint which, I must admit, are not very well chosen (it’s what I needed to model a rope). The stetched and compressed spring constants are the only ‘real’ spring constants. If the spring is stretched or compressed beyond the limits ste by min- and maxSpringSize, the involved body’s impulses travel over the spring directly, as if the bodies are directly connected at the joint axes. Since the simulation is done in discrete steps, the spring can be stretched or compressed beyond its limits too far, the brokenStringConst determines how much force is used to correct this.

First, all of your points are well taken. I appreciate the further explanation of how to use SpringJoint. It will likely help others with little physics knowledge retention from college (even high school).

I imagine that using this joint in the way in which I had intended would result in crap, for lack of a better word.

I am simply trying to find some ways to create some nice physics effects outside the standard rigid physics…and like I mentioned, I have much to little understanding of physics to do much damage on my own.