Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

Detecting a touch on a mesh

edited June 2012 in Questions Posts: 10

I've got a project that draws a lot of triangles. I have found that using a mesh gives me a nice triangle, but I can't figure out how to detect a touch on an individual triangle. I found this page, http://www.blackpawn.com/texts/pointinpoly/default.html , and I'm trying to implement the algorithm at the end, but it's not working.

At first, I had A, B, C and P set up as vec2, but that didn't work, so I Googled some more and I think I need to use vec3. Because I'm translating my matrix when I draw the triangle, I'm trying to add the position to the vertices as well.

These are new concepts for me. I would be grateful for any assistance. I'd also be happy if there was some method I've overlooked that can do this simply.


function Pyramid:init(x, y)
    self.position = vec2(x, y)
    self.mesh = mesh()
    self.mesh.vertices = {vec2(0, 0), vec2(100, 0), vec2(50, 100)}
    self.size = SMALL
    self.color = GREEN
    self.selected = false
end

function Pyramid:hit(touch)
    local pos = vec3(self.position.x, self.position.y, 0)
    local A = vec3(self.mesh.vertices[1].x, self.mesh.vertices[1].y, 0) + pos
    local B = vec3(self.mesh.vertices[2].x, self.mesh.vertices[2].y, 0) + pos
    local C = vec3(self.mesh.vertices[3].x, self.mesh.vertices[3].y, 0) + pos
    local P = vec3(touch.x, touch.y, 0)
    
    local v0 = C - A
    local v1 = B - A
    local v2 = P - A
        
    local dot00 = v0:dot(v0)
    local dot01 = v0:dot(v1)
    local dot02 = v0:dot(v2)
    local dot11 = v1:dot(v1)
    local dot12 = v1:dot(v2)
    
    local invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
    local u = (dot11 * dot02 - dot01 * dot12) * invDenom
    local v = (dot00 * dot12 - dot01 * dot02) * invDenom
    
    return (u >= 0) and (v >= 0) and (u + v < 1)
end
Tagged:

Comments

  • SimeonSimeon Admin Mod
    Posts: 5,028

    You could try constructing a static physics body from your triangles and then using an AABB query to perform the hit-test.

    This should be very fast as the physics engine (Box2D) uses fairly fast spatial partitioning

  • Posts: 10

    Thanks! I'll give that a try.

    Just as soon as I learn how to do it! ;-)

  • Posts: 10

    Okie dokie! I've got something working. Here are the relevant bits of code:

    function Pyramid:init(x, y)
        self.position = vec2(x, y)
        self.size = SMALL
        self.color = GREEN
        self.selected = false
    end
    
    function Pyramid:addBody()
        local pos = self.position
        local vert = {vec2(0, 0), vec2(100, 0), vec2(50, 100)}
        
        self.mesh = mesh()
        self.mesh.vertices = vert
        
        self.body = physics.body(POLYGON, vert[1] * self.size + pos,
                                          vert[2] * self.size + pos,
                                          vert[3] * self.size + pos)
        self.body.type = STATIC
    end
    
    function Pyramid:hit(touch)
        local x = physics.queryAABB(vec2(touch.x, touch.y), vec2(touch.x, touch.y))
        return x[1] == self.body
    end

    I pulled the mesh and body creation to a different function because I assumed that if the init function created the body before I could set the size (which I prefer to keep out of the init parameters), then I'd have a harder time resetting the body.

    I couldn't find a way to scale and translate the physics body, which means that my mesh is a different size than my body. I find this to be a little inelegant, but my attempt at reconciling the two didn't work so I'm just declaring victory and moving on. :-)

    Thanks for the help!

  • Posts: 10

    And I've figured out that I can set the position of the physics body, so now I'm not adding the position to the body when I create it, just when I'm drawing the mesh. Now my init function looks like this:

    function Pyramid:init(size, color)
        self.size = size
        self.color = color
        self.selected = false
    end

    The position of the triangles will be calculated, so there's no reason for me to keep that state in the object.

    Hm. Now I think I can roll the mesh and physics body creation back into the init function.

Sign In or Register to comment.