Fixture Resizing?

Topics: User Forum
Mar 11, 2011 at 5:43 AM

I have a pretty simple question.

I want to resize a Fixture during gameplay.

How would I do this?

I have attempted to remove and delete the fixture and then replace it in the same frame, but this causes a flurry of errors.

Any suggestions?

Thanks!

Developer
Mar 29, 2011 at 4:29 PM

Removing and adding a bigger fixture should work from one frame to the next. Is there a special reason you need them replaced during one frame?

Another solution would be to add several fixtures of different sizes to the same body and only activate one of them, by setting them en or disabled.

If you want to resize the fixture continuously that should also be possible, as long as the amount of vertices stays the same. You might get trouble with cached contacts etc. though, so this approach might need some tweaking around.

Sep 8, 2011 at 4:08 AM
Elsch wrote:

If you want to resize the fixture continuously that should also be possible, as long as the amount of vertices stays the same. You might get trouble with cached contacts etc. though, so this approach might need some tweaking around.

Hi Elsch,

I'm interested in this method of doing it for FP3. How would you go about modifying the vertices of a fixture? When I access a fixture via Body.FixtureList[0], I don't see any methods or members exposed for doing this.

Thanks!

Sep 27, 2011 at 6:55 AM

Hello!

I too am interested to find a solution for this particular issue. This would be very useful for objects which morph and have dynamic hitboxes. Thanks in advance!

Jan 14, 2012 at 3:20 AM

Friendly ping on this thread. Any of the Farseer developers have a solution / workaround for v3?

Thanks.

Jan 22, 2012 at 12:43 AM

A PolygonShape has public Vertices and Normals so how about modifying them directly and then calling ComputeProperies().

Feb 23, 2012 at 3:35 PM
Edited Feb 24, 2012 at 8:19 AM

 

Absolutely with a PolygonShape , you can use public methods such as Scale, Translate, Rotate (and so on...) exposed by the Vertices class to apply some changes to a body. It works even without calling ComputeProperties() or any kind of "refresh" method for me.

But (one of) the problem is that when you change theses values directly (without "submitting it to the engine before" like a joint would do), no constraint is applied to your scale/resize action. As a result, nothing stops you from increasing your body indefinitely even if it collides with statics objects for example...

Another ping to this thread, if someone got a solution to handle this scale/resize behavior, thanks in advance!

Feb 23, 2012 at 8:01 PM
Edited Feb 23, 2012 at 11:24 PM

If you manipulate the Vertices direclty (as opposed to calling Set(Vertices)) and don't call ComputeProperties then the mass data for the polygon is wrong (mass, centroid and inertia). 

Shrinking a shape is easy because it frees space. Growing a shape is hard. If we think about it in the physical sense - it's unrealistic (magic?) as something doesn't grow in zero time (perhaps it grows in very small steps thus being subjected to the world's forces in those small steps). 

In my simulation I have a thin rod that should grow under user input. The only way to make it happen without eventually getting stuck into static objects was to first move the tip body under a force. The tip body is linked to the rest with a prismatic joint so I know that there is certain space behind it that is free. Only once this space is enough (joint translation is at it's limit, doesn't allow rotation) I modify the shape to a new larger size. I'm lucky my rod only grows in one dimension - width. I don't think it's possible to grow it like this in 2D without first checking if there is enough empty space around.

Another possibility I have thought is to have an extra larger "ghost" body that is linked to the smaller one, shadows it but does not affect it back while still getting collisions from the world. So when you grow you just pass from the smaller body to the larger body and create a new large body for the next growth step in some empty space if available (not perfect). 

Feb 29, 2012 at 6:02 PM

Any Tutorials about this somewhere?

Mar 8, 2012 at 6:25 PM

For reference Erin Catto (creator of Box2D) has just posted a great presentation part of which specifically deals with the problem of spawning ragdolls that get stuck in the terrain and how to deal with it (conclusion: there is no silver bullet):

http://box2d.googlecode.com/files/GDC2012_ErinCatto_Ragdolls.pdf

Nov 1, 2012 at 10:47 AM
Edited Nov 1, 2012 at 11:04 AM

Hi,

I tried the suggestion here of accessing the Vertices directly in the PolygonShape class and calling Scale()

for example:

 

                foreach (Fixture fix in body.FixtureList)
                {
                    ((PolygonShape)fix.Shape).Vertices.Scale(ref scalepercent);
                }

That however resulted in a lot of bodies spazzing out when they contacted a resized object. I ended up copying the Vertices to a List, destroying the fixtures, then re-attaching the Vertices list, which works perfectly:

 

                List<Vertices> temp = new List<Vertices>();
                foreach (Fixture fix in body.FixtureList)
                {
                    ((PolygonShape)fix.Shape).Vertices.Scale(ref scalepercent);
                    temp.Add(((PolygonShape) fix.Shape).Vertices);
                }
                for (int i = 0; i < body.FixtureList.Count; )
                {
                    body.DestroyFixture(bto.Body.FixtureList[i]);
                }

                FixtureFactory.AttachCompoundPolygon(temp, 1, body);

 

 

Does anyone know why this works better? I'll have to pick around the source to figure out what's going on because I'm sure there's a far more efficient way to do this.

thanks 

edit:

ok, this is probably slightly better...

                Shape[] temp = new Shape[body.FixtureList.Count];

                for (int i = 0; i < body.FixtureList.Count; i++)
                {
                    ((PolygonShape)body.FixtureList[i].Shape).Vertices.Scale(ref scalepercent);
                    PolygonShape shape = new PolygonShape(((PolygonShape)body.FixtureList[i].Shape).Vertices, 1);
                    temp[i] = shape;
                }
                foreach (Shape x in temp)
                {
                    body.CreateFixture(x, null);    
                }

Coordinator
Nov 2, 2012 at 4:33 PM

I would not recommend manipulating the vertices of a shape directly. It will in cases of rotation and translation cause trouble for the engine, as the values are updated without the engine's knowledge, causing it to blow up. I would not expect scaling to cause as much trouble, but the mass values for the shape is going to be wrong.

The solution that will always work is what Elsch proposed. Create a new shape that is larger, destroy the old fixture and create a new.