Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat
Getting the normal from a collision - Gideros Forum

Getting the normal from a collision

StoffeStoffe Member
edited November 2011 in General questions
I'm rolling a ball around on EdgeShapes, could use triangles as well if that would help. The ball can be rolling on any surface, even upside down and on sides etc. Let's say I want a flag or something sticking straight up from the ball, out from the "ground", that is to say, take the normal of the collision (or average of collisions when several side-by-side, as in corners) and rotate a sprite attached to the ball (if that's the best way to do it).

In regular box2d there seems to be a way to get it, think it was called localNormal or something similar, also possible to get touch points etc. I can't find it here.

Also, calculating this proved to be a bit more difficult than I thought and my trigonometry is kind of rusty. Doing it manually involves having the angle of the EdgeShape and knowing which side of the line the ball is, as well as knowing the "direction" of the line. All of which should be knowable, and I can probably brute force it :) but I would really like to hear if this is an already solved problem that someone could share? Thanks!

Especially solutions that does it completely different extra welcome, because usually we have a tendency to not see the forest for the trees, and there is probably something easy and elegant I'm missing here. :)

(Also, hope you get the chain shapes in the next version, seems like a much better way to do it for a project like mine!)

Comments

  • atilimatilim Maintainer
    Hi Stoffe,

    Can you draw a simple figure and post here that describes your problem? :-? This way I can understand it in a more detail.

    Currently we don't provide information about contact points (only maxImpulse value at POST_SOLVE event). We can add this feature to the next version.

    As you know, chain shapes are very recently added to box2d (at v2.2.0). We're waiting a little bit before supporting it because we want to be sure that its API is stable.
  • Sure, something like this? http://imgur.com/5ZkCi

    I need the angle of the normal of the ground the ball is currently on, so I can set the same in the flag. There are several way to derive this, but not sure which is best or which ones ar even possible.

    Knowing the angle of the EdgeShape is enough if I also know which side of the edge the ball is - if the edge is tilted at 45 degrees, the normal is 90+45 on one side, but 45-90 on the other side, so to speak.

    Actually finding that out is harder than what I thought, and my first experiments with some formulas on the internet didn't really work, I think maybe partly because they assumed infinite lines? Could just be me as well.

    So maybe it would be easier to compare with a contact point. I should be able to get an approximate contact point since it's a circle and I have the triangle of center of circle + endpoints of line. Using that should probably make it possible to compare what side of the line I'm at.

    Anyhow, I would be very thankful for some advice on this, especially if there are some properties I could take advantage of that I may not know of, or if someone already know how to calculate this could provide me with an example or a formula.

    It's safe to assume CircleShape + EdgeShape, BUT I could switch to triangulated ground areas if that would help.

    Hope that was clearer!
  • atilimatilim Maintainer
    edited November 2011
    Hi,

    I understand now :)

    If your edges always form a polygon and if your ball always stays outside of your polygons, you may use this solution:

    1. Form your polygons always counterclockwise. (clockwise is also ok but you need to negate the formulas)

    2. If you have an edge from v1 to v2, do the calculation below to find the normal vector outside:
    -- direction (tangent) vector of edge
    dx = v2.x - v1.x
    dy = v2.y - v1.y
     
    -- optionally you can normalize the vector (dx, dy) here
     
    -- normal vector of edge
    nx = -dy
    ny = dx
    3. You can use the events Event.BEGIN_CONTACT and Event.END_CONTACT to find the contacting edges.
    local function onBeginContact(event)
      local fixtureA= event.fixtureA --> contacting fixture A
      local fixtureB = event.fixtureB --> contacting fixture B
      local bodyA = fixtureA:getBody() --> contacting body A
      local bodyB = fixtureB:getBody() --> contacting body B
    end
     
    local function onEndContact(event)
      -- similar
    end
     
    world:addEventListener(Event.BEGIN_CONTACT, onBeginContact)
    world:addEventListener(Event.END_CONTACT , onEndContact)
  • Ah yes, forming complete polygons is an acceptable restriction, as is enforcing a direction I would say. I'll try this, thanks!
Sign In or Register to comment.