Detecting a touch on a mesh

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
`

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

Thanks! I’ll give that a try.

Just as soon as I learn how to do it! :wink:

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. :slight_smile:

Thanks for the help!

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.