Howdy, Stranger!

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

Advanced touch detection [SOLVED]

edited January 2015 in General Posts: 11

I have a sample code like this

function draw()
    translate(300,300)
    rotate(30)
    scale(2,1.5)

    fill(255, 255, 255, 255)
    rect(0,0,100,100)
end

Which draws a tilted rectangle somewhere on the screen. I wonder how can I detect if a given point (e.g. touch) is inside the rectangle? Any thoughts are appreciated.

SOLUTION

Thanks to @Ignatz and @LoopSpace I ended up with pretty simple and elegant solution for 2D rects. Just few lines of code allow to convert a point from world coordinates to current matrix and vice verse. The full code is below.

mm = matrix()

function draw()    
    translate(300,300)
    rotate(30)
    scale(2,1.5)

    fill(255, 255, 255, 255)
    rect(0,0,100,100)

    mm = modelMatrix()
end

function touched(touch)
    if touch.state ~= BEGAN then return end

    local localPoint = worldToLocal(touch)
    local worldPoint = localToWorld(localPoint)

    print(touch.x, touch.y) -- the original touch point
    print(localPoint)       -- the point in rect coordinates
    print(worldPoint)       -- this should be the same as the original touch

    if localPoint.x >= 0 and localPoint.x <= 100 and
    localPoint.y >= 0 and localPoint.y <= 100 then
        print("HIT!")
    end
end

function multiplyVec2ByMatrix(vec, mat)
    vec = vec4(vec.x, vec.y, 0, 1)
    -- Normaly the code below should look like "local resultVec = mat*vec"
    -- but as soon as something is broken in Codea right now multiply them manualy
    local resultVec = vec4(
        mat[1]*vec[1] + mat[5]*vec[2] + mat[09]*vec[3] + mat[13]*vec[4],
        mat[2]*vec[1] + mat[6]*vec[2] + mat[10]*vec[3] + mat[14]*vec[4],
        mat[3]*vec[1] + mat[7]*vec[2] + mat[11]*vec[3] + mat[15]*vec[4],
        mat[4]*vec[1] + mat[8]*vec[2] + mat[12]*vec[3] + mat[16]*vec[4]
    )
    return vec2(resultVec.x, resultVec.y)
end

function localToWorld(localPoint)
    return multiplyVec2ByMatrix(localPoint, mm)
end

function worldToLocal(worldPoint)
    if mm:determinant() == 0 then
        return nil
    else
        local resultVec = multiplyVec2ByMatrix(worldPoint, mm:inverse())
        return vec2(resultVec.x, resultVec.y)
    end
end

Comments

Sign In or Register to comment.