Can you make a polygonal body clamp to an edge (as if magnetic) in Box2D?

I’m considering whether or not to use Box2D for a project.

I need a way of getting a polygon body to stick to an (immobile) edge upon contact, as if they are gently magnetized, but I’m not sure whether this would be possible in Box2D. I’m not trying to model attraction between them, just the stickiness (perhaps velcro would’ve been a better analogy…)

In past projects, I’ve tried something similar to this, where you create a weld joint when you detect a collision. But sometimes this means the polygon just gets welded by one corner (whereas really you want a larger contact surface); or worse, if the polygon is moving at speed when it hits the surface, it has already started to bounce off, so it ends up being welded a distance away from the edge.

I guess the basic problem is that this “magnetism” works against restitution and the Box2D constraint system.

I guess you’d need to know the normal of the edge, and the normal of the nearest edge of the polygon, rotate and move the polygon into alignment (maybe temporarily convert it into a kinematic object to overcome restitution and object constraints?) and then weld it??

I’d be interested if anyone has an opinion as to whether this is feasible in Box2D, or would I just be creating too much work for myself in fighting the constraint system?

Have you tried adjusting the linearVelocity to get the effect you want, ie on colliding with the surface, set it to a fraction of the distance between the object and the surface (assuming it has already bounced off), so it is pulled gently back towards the surface.

EDIT - tried it and it seems to work

I’ll experiment with that. I’ve got a feeling though that propelling the objects towards one another will make them bounce off. I’ll report back

@yojimbo2000 Thought I’d give it a try. This kind of works.

supportedOrientations(LANDSCAPE_ANY)

function setup()
    rectMode(CENTER)
    e=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT))
    e.info="edge"
    e.friction=1
    
    b=physics.body(CIRCLE,10)
    b.x=WIDTH/2
    b.y=350
    b.type=STATIC
    
    size=25
    p=physics.body(POLYGON,vec2(-size,size),vec2(-size,-size),vec2(size,-size),vec2(size,size))
    p.x=WIDTH/2+12
    p.y=600
    p.restitution=1.3
    p.info="poly"
    p.friction=1
end

function draw()
    background(0)
    fill(255)
    ellipse(b.x,b.y,20)
    pushMatrix()
    if m then
        p.restitution=0
        p.linearVelocity=vec2(10,0)
    end
    translate(p.x,p.y)
    rotate(p.angle)
    rect(0,0,size*2,size*2)
    popMatrix()
end

function collide(c)
    if c.state==BEGAN then
        if c.bodyA.info=="edge" and c.bodyB.info=="poly" or
                c.bodyA.info=="poly" and c.bodyB.info=="edge" then
            m=true
        end
    end
end

I tested this version

   p.linearVelocity=vec2((wall.x-p.x)/5,0)

which is similar, except it slows down as it gets closer

Hello.
I’m a total noob learning how to program. But I used Box2D for one of my assignments. I had the opposite problem where I had polygons sticking to the static edge and sliding. I managed to fix it by adjusting my scale, friction, angular and linear clamp, but also adjusting my velocity threshold for inelastic collisions.

It’s in Box2D\Common\b2Settings.h

b2_velocityThreshold

If you haven’t already played with this setting, you could try increasing it so it negates the restitution… I can’t remember if it changes the minimum or maximum velocity for elastic/inelastic… I haven’t played around in B2 for a about a month now as I’m working on a new assignment.
But I had done some experimenting with a pseudo-magnetic force by adding my own formulas to a Solar System simulation that I was practicing on.
I’m using Mass to attract other objects.
I also tried to make a self propelling particle using Electromagnetic Forces after talking to a classmate about rail guns… that project got put on a to-do-when-i-have time-list as I was getting too side tracked with random stuff that wasn’t for assessments…

**edit: I was using VS C++ … I’m not even sure if the same settings are there for Codea/Lua… I’m guessing it would be.

@Dave1707 @Ignatz

Cool, thanks for that. So friction up, restitution down, and a tiny bit of force applied. It actually works well with low amounts of restitution (ie 0.2 or whatever, it doesn’t have to go down to zero). The friction is key I think to the stickiness.

Thank you both!

@NeoBeum

managed to fix it by adjusting my scale, friction, angular and linear clamp, but also adjusting my velocity threshold for inelastic collisions.

Codea gives us access to all of those (if linear/ angular clamp is damping?), except maybe the last one, velocity threshold.

Actually I think the pixel scale is a key property to modify, as it effects the entire feel of the simulation. If you feel everything is happening in slow motion, like bodies seem to hang in the air for too long, then increasing the ratio (ie making the physical objects smaller in the simulation) really speeds everything up.

Actually, if you use this adjustment for linearVelocity in dave’s code above, you don’t need to touch friction or restitution.

p.linearVelocity =vec2((WIDTH-b.x)/100,0)

Codea gives us access to all of those (if linear/ angular clamp is damping?), except maybe the last one, velocity threshold.

yeah, damping… clamping… damping… potato tomato… sorry, was about 1am when i was writing this…

i started with a 1ft:0.5m:100px scale, i built a pool/bowling game, but because i used to play pool semi-competitively in real life, i know the american pool table measurements off by heart. so my measurements were in feet, box2d was in metres, and sfml display used pixels… 9ft table in my head, 4.5m b2 table, 900px draw, that scale didn’t work so well…
when i looked at what was happening in debug… the objects were still moving and had velocity, but at 0.000000X … so visually, the screen didn’t know how to translate the tiny movement… so the balls stuck to the edge.

i changed my scale to 1ft:25m:100px… it fixed it… but my first attempt at using my own math library, i did the conversion wrong, and my cue ball was displaced 22km away from where it was meant to be… the ball also travelled at mach 1.

if you scale too high, you’ll notice that objects will hit a terminal velocity… i did an experiment where my screen was the equivalent of about 900 m… and the object under gravity would hit a peak at around 200m/s …

also, the timestep can have an impact on the motion visually… i ended up using a deltaTime from start, but i was experimenting with fixed 1/60, 1/50 or around 0.1125 to 0.15 seconds … but the deltatime was smoother on faster machines… i had to use a fixed rate on my laptop because it was drawing really slowly.

edit: got a bit side tracked - (woops) comment below was meant to be in this edit… gosh i’m still sleepy…

velocityThreshold in b2Settings.h was a setting I tweaked around the most to get the collision right, you may be able to do the opposite of my bounce, and get it to stick like I had it sticking by fiddling around with the threshold.

i also wrote a little bit of a deceleration code - which slowed down velocity faster the slower the object was moving, then when it reached a certain point (the point where the screen can’t tell if it should draw 0.0005 of a pixed), i just zeroed the velocity completely.
i increased linearDamping, and decreased velocity by a factor at the same time.

tweaking the density of the objects can have some effect on the collision also