Page 1 of 1

Contact normals between circle shapes

Posted: Tue Jun 28, 2011 3:49 pm
by lizard
I'm confused. Why in some cases the normal vector is calculated incorrectly (with negative sign)? This only occurs with CircleShapes.
Image

Re: Contact normals between circle shapes

Posted: Tue Jun 28, 2011 6:29 pm
by vrld
I'm also confused. Could you be a little more specific?
  • What do you want to do?
  • What result did you expect to get?
  • What did you get instead?
  • In what circumstances does the error occur?

Re: Contact normals between circle shapes

Posted: Tue Jun 28, 2011 9:40 pm
by miko
lizard wrote:I'm confused. Why in some cases the normal vector is calculated incorrectly (with negative sign)? This only occurs with CircleShapes.
Image
I have not looked at your code nor run the example, but I bet it is a known arcus tangent "problem". If you are using math.atan, try math.atan2 instead.

http://en.wikipedia.org/wiki/Atan2

Re: Contact normals between circle shapes

Posted: Tue Jun 28, 2011 9:46 pm
by ivan
lizard wrote:I'm confused. Why in some cases the normal vector is calculated incorrectly (with negative sign)? This only occurs with CircleShapes.
I think your question is not very clear. A vector or rather the length of a vector cannot be negative.
I suspect you are talking about Box2D's 'normalImpulse' value which is given during the collision result callback.
This is what the official Box2D documentation says regarding normalImpulse:
normal impulse
The normal force is the force applied at a contact point to prevent the shapes from penetrating. For convenience, Box2D works with impulses. The normal impulse is just the normal force multiplied by the time step.

Re: Contact normals between circle shapes

Posted: Wed Jun 29, 2011 12:29 pm
by lizard
Well, I'm trying to set angle of sprite according to the angle of inclination of the surface, and apply a jump impulse by normal impulse vector.
But in some cases (only with circle shapes) normal impulse vector calculated in another direction.
Position 1:
Image
Position 2:
Image
Position 1 calculated correctly, 2 - in opposite direction. This can be box2d glitch? When 'persist' callback called more one times? Or am I wrong to understand some of the box2d features?
Slightly different code of first post variant:

Code: Select all

function Pony:cb_persist(object,contact)
    local cx,cy = contact:getPosition()
    local x,y = self.position:unpack()
    if cy > y and (cx >= x-(self.size-10)) and (cx <= x + (self.size-10)) then
        if instanceOf(Platform, object) or instanceOf(DynamicBody, object) or instanceOf(Actor, object) then
            self.stand_on = object
            self.cx = cx --contact position
            self.cy = cy
            self.nx,self.ny = contact:getNormal() --contact normal
            self.angle = math.atan2(self.nx,-self.ny) --sprite angle
        end
    end
    if (self.orientation*(x-cx) < -10) then --touching at front
        if instanceOf(DynamicBody, object) or instanceOf(Actor, object) then --this object can be grabbed
            self.touching = object
            self.tx = cx
            self.ty = cy
        end
    end
end
PS. Sorry, ugly english.

Re: Contact normals between circle shapes

Posted: Wed Jun 29, 2011 1:04 pm
by kikito
I'm not sure this is the problem, but it could be related with the fact that when you have two objects A and B touching:

A "touches" B

but also

B "touches" A.

I'm not sure about how Box2d deals with this. Does it call the "callback" function twice, once for A and B, and another for B and A, or just once, with A and B randomly? I don't know.

On the first case (there are two calls), what is happening is that you are getting two calls for each of your "touching ponies". One of them calculates the normal correctly, and the other returns the inverse normal (because it's the normal "perceived by pony B, not pony A"). Sometimes the "correct" one is the last one, so you get the correct normal. Other times the "inverse" is the last called, so it "overwrites" the "correct" normal.

You have to "detect and deactivate" that second case.

It seems to me that there is the implicit assumption in your image that "the pony on top" should change its orientation, while the "pony at the bottom" should not. You have to put an "if" in your code to "check that I'm the pony on the top".

If there is only one callback, then A and B are being chosen (seemingly) ramdomly - Sometimes "the pony on the top" will be self, and sometimes it will be "object". You will have to use the normal when "self" is on the top, and the inverse normal when "self" is on the bottom.

I hope this makes sense.

Re: Contact normals between circle shapes

Posted: Wed Jun 29, 2011 1:43 pm
by ivan
kikito wrote:I'm not sure about how Box2d deals with this. Does it call the "callback" function twice, once for A and B, and another for B and A, or just once, with A and B randomly? I don't know.
Yeah, I'm pretty sure that's how Box2D reports collisions.
So you usually get 2 callbacks for a pair of colliding shapes, EXCEPT if one of the shapes is static.
If one of the shapes is static like in this picture you get one callback:
Image

If the two shapes are non-static you get two callbacks for one pair of colliding shapes:
Image

This seems to make sense because forces and impulses are not applied to static shapes.
I'd have to look at the Box2D code but I'm almost 100% sure that's how it works.