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