Complex polygons with Box2D

Hi all!

I’m trying to fix different shapes(triangle) in the same body so to create a complex polygon. Does anybody know how to do it?

Thanks.

Sounds like you need to work out the delaunay triangulation within the complex polygon.

Vanderlin has done some work with this,

http://toddvanderlin.com/2009/04/delaunay-contour/

L.

Hi!

Here is a small addon (with example) that wraps triangle c++ wrapper from Piyush Kumar for openframeworks according to the method described by Todd in his blog. It also uses the great PointInsidePolygon function of Theo! You can use these triangles to reproduce your shape in box2d.

ofxTriangle

hope it helps!

update: memory leak fixed! ^^

very cool kikko, thanks for sharing that.

can you think of any way of stabilising the triangles?
looks like on every frame it works out a new contour and re-calculates all the triangles.

just trying to think of ways of smoothing out the triangle transitions…

L.

I think you find the triangulation messy because the debug drawing gives a random color for each triangle on every update. It looks way more stable when you only draw the strokes of the triangles!

I’m not sure about the best way to interpolate the triangles instead of replacing on each update. But if your goal is to use the triangles as rigid bodies for human interactions, it’s likely that you want them to be accurate as often as possible!

That’s good stuff!

Thank you both!

There’s still a problem when I want to assemble all these triangles in the same body. Most of the time the program fail.

Here the code, maybe you can see what could be the problem :?

  
  
void init(b2World * b2dworld, float x, float y, float fMass, float fFriction, vector<ofPoint> pTriangleA, vector<ofPoint>  pTriangleB, vector<ofPoint>  pTriangleC)  
{  
	if(b2dworld == NULL) {  
		ofLog(OF_LOG_NOTICE, "- must have a valid world -");  
		return;  
	}  
  
	world = b2dworld;  
  
	b2BodyDef bodyDef;  
	bodyDef.position.Set(x/OFX_BOX2D_SCALE, y/OFX_BOX2D_SCALE);  
	body = world->CreateBody(&bodyDef);  
  
  
        int iCptPoly=0;  
	for(int i=0;i<pTriangleA.size();i++)  
	{  
            b2PolygonDef poly;  
            poly.vertexCount = 3;  
  
            poly.density	     = fMass;  
            poly.restitution     = 0.0;  
            poly.friction	     = fFriction;  
  
            poly.vertices[0].Set(pTriangleA[i].x, pTriangleA[i].y);  
            poly.vertices[1].Set(pTriangleB[i].x, pTriangleB[i].y);  
            poly.vertices[2].Set(pTriangleC[i].x, pTriangleC[i].y);  
  
            for(int j=0;j<3;j++)  
            {  
                poly.vertices[j].x /= OFX_BOX2D_SCALE;  
                poly.vertices[j].y /= OFX_BOX2D_SCALE;  
            }  
            
            body->CreateShape(&poly);  ///--------->IT FAIL THERE<-------  
	}  
  
       body->SetMassFromShapes();  
  
	//set the filter data  
	b2FilterData data;  
	data.categoryBits = 0x0003;  
	data.maskBits = 0x1;  
	data.groupIndex = -3;  
}  
  

Thanks

If it’s a box2d assertion that make your app crash, it’s probably because the points have to be ordered clockwise and the triangles have to fit some requirements :

  • Edges can’t be too close to parallel
  • Area must be greater than a minimum value
  • Each edge must be more than b2_toiSlop away from the centroid

I haven’t figured yet how to perform these checks but I’ll give it a try in the next couple of days!

well after doing some researches i found out 2 things :

  • first is that plong0 made a similar addon (ofxDelaunay) a couple of months ago that may be faster than the one i posted!
  • second is that Todd Vanderlin already did all the maths of the polygon requierements in the ofxBox2dPolygon.validateShape() method! so for us, validating a triangle is as easy as :
  
ofxBox2dPolygon poly;  
poly.addVertex(tData->a.x, tData->a.y);  
poly.addVertex(tData->b.x, tData->b.y);  
poly.addVertex(tData->c.x, tData->c.y);  
			  
if(poly.validateShape()) {  
			  
	poly.init(physics.world, 0.0f, 0.0f);  
}  

awesome! thanks for that Todd!^^

sources-of-the-example-below

Hi kikko and all.
Thank you all for sharing code and info :slight_smile:

i did some experiments using ofxTriangle.

http://vimeo.com/9951522

[attachment=99:1g2pno6b]BlobToB2D.zip[/attachment:1g2pno6b]
**edit 20100506**
this is depreciated.
new version is http://forum.openframeworks.cc/t/complex-polygons-with-box2d/3386/24

In this experiment, i did some awkward hack to stop box2d assertion.
At b2Settings.h, before #include <assert.h>, place #define NDEBUG.

And how to create custome polygon:
http://www.psyked.co.uk/box2d/simple-box2d-custom-polygon-creation.htm

  
  
void testApp::makeComplexBody(b2Body* body, vector<ofxTriangleData*> triangles) {  
	int shapeCnt = 0;  
	  
	for (int i = 0; i < triangles.size(); i++) {  
	  
		b2PolygonDef* shapeDef = new b2PolygonDef();  
		shapeDef->density = 1;  
		shapeDef->friction = 5;  
		shapeDef->vertexCount = 3;  
  
		shapeDef->vertices[0].Set(triangles[i]->a.x/OFX_BOX2D_SCALE, triangles[i]->a.y/OFX_BOX2D_SCALE);  
		shapeDef->vertices[1].Set(triangles[i]->b.x/OFX_BOX2D_SCALE, triangles[i]->b.y/OFX_BOX2D_SCALE);  
		shapeDef->vertices[2].Set(triangles[i]->c.x/OFX_BOX2D_SCALE, triangles[i]->c.y/OFX_BOX2D_SCALE);  
		  
		body->CreateShape(shapeDef);  
		shapeCnt++;  
	}  
	  
	shapeCnts.push_back(shapeCnt);  
	body->SetMassFromShapes();  
}  
  

cheers

BlobToB2D.zip

sweet idea and video Akira! love it!

Nice sharing!

Thanks you both!

hi kikko,

im trying to run your example but running into problems, think its do with my version of ofxBox2d.

i got the latest from vanderlin’s trunk (rev 73) http://code.google.com/p/vanderlin/ and ofxBox2dPolygon is missing the validateShape() method you call in your code.
not sure why it has been removed.

so i went back a revision to rev 72 and i was able to compile your code but running into this error,

Assertion failed: (m_I > 0.0f), function SetMassFromShapes, file /Volumes/STORAGE/OF_0061/apps/forum/3386_ofxTriangle_box2d/…/…/…/addons/ofxBox2d_rev72/scr/lib/Box2D/Source/Dynamics/b2Body.cpp, line 334.
Program received signal: “SIGABRT”.

would you mind posting your version of ofxBox2d you are using for your example?

really keen to get it working.

thx, L.

hi julapy,

my knowledge in box2d is quite basic so I can’t tell you why your shape is unable to get a mass even if it has been checked by Todd’s function…

here is the version I’m working with hope it helps!

ofxBox2d.zip

hey kikko, works great now!
thx for posting.

Nice work guys, really interesting and with many possibilities :smiley:

I have been working on a ton of simple demos for people to play with (will get up soon). I have fixed the polygon support in the addon - the latest in the svn is good. Here is an example on a simple triangles

http://toddvanderlin.com/OF/Triangles.zip

![](http://forum.openframeworks.cc/uploads/default/637/Screen shot 2010-03-15 at 10.50.07 AM.png)

Hi,

great work guys.
I still can’t get Akiras Demo to work.
with makeComplexBody(body, tri.triangles); commented out it will crash with a sigsev when I want the shape that is captured to be transformed to a box2d shape, with it in the code I can’t compile because I get those errors:

  
C:\code\of_preRelease_v0061\apps\myapps\test_ofxtriangle\testApp.cpp:87: error: no matching function for call to `testApp::makeComplexBody(b2Body*&, std::vector<ofxTriangleData, std::allocator<ofxTriangleData> >&)'  
C:\code\of_preRelease_v0061\apps\myapps\test_ofxtriangle\testApp.h:26: note: candidates are: void testApp::makeComplexBody(b2Body*, std::vector<ofxTriangleData*, std::allocator<ofxTriangleData*> >)  
  

I can’t see a difference, I am using it like defined in my code…

Hi snoogie.

  1. with makeComplexBody (you got “no matching function” error)

you pass wrong parameter to makeComplexBody function.
you need to pass correct param like below

  
b2BodyDef* bodyDef = new b2BodyDef();  
bodyDef->position.Set(360/OFX_BOX2D_SCALE, 20/OFX_BOX2D_SCALE);  
bodyDef->linearDamping = 0.25;  
bodyDef->angularDamping = 0.25;  
b2Body* body = box2d.getWorld()->CreateBody(bodyDef);	  
makeComplexBody(body, tri.triangles);  

  1. commented out makeComplexBody (you got SIGSEGV error)

testApp::draw() function uses b2Shape data to draw polygon.
And makeComplexBody create b2Shape data from triangulated contour.
if you commented out makeComplexBody function,
though testApp::draw() function try to draw polygon, there is no b2Shape data.

comment out all b2Shape related line
or
make appropriate b2Shape data

hope this help…

Hey Akria,

thanks for the reply. I am passing the params like you said (actually I am using exactly your uploaded example) but I still get that error. I think I can track it down to the tri.triangles.
It seems like tri.triangles is not the right type (although I haven’t changed anything in ofxtriangle either)

I include an attachment which shows what tri.triangles & body have stored.
That should be exactly what is meant to be passed to “makecomplexbodies”.

Any more sugestions? :slight_smile:

Cheers
Snoogie

Edit of Edit:
I found out that I pass vector instead of the expected vector<ofxTriangleData*>

Why is that?
I use the original Version of Kikkos ofxTriangle addon which works fine with the example by kikko.
So tri.triangle returns the wrong thing but why?
I am relative new to c++

Can please anybody try Akiras example and tell me if it works for him?
Thanks in advance
Snoogie