Page Turn Effect

Hey all! I just wanted to share my latest project before going to bed, it is a page simulator (like iBooks). The code is also up on CC. (It’s super messy and kinda slow, but I’ll fix it up later)

--The name of the project must match your Codea project name if dependencies are used. 
--Project: Page Flip
--Version: Alpha 1.1
--Comments:

-- Page Flip
displayMode(FULLSCREEN)
-- code based from http://rbarraza.com/html5-canvas-pageflip/
-- Use this function to perform your initial setup
function setup()
    fps = 60
    page = { w = 420, h = 594, }
    page.b = HEIGHT / 2 - page.h / 2
    page.t = HEIGHT / 2 + page.h / 2
    page.l = WIDTH / 2 - page.w
    page.r = WIDTH / 2 + page.w
    t = { x = page.r, y = page.b, tx = page.r, ty = page.b }
    flip = mesh()
end

-- This function gets called once every frame
function draw()
    background(127, 255)
    rectMode(CORNER)
    noStroke()
    fill(255, 255, 255, 255)
    fps = fps *  59 / 60 + 1 / DeltaTime / 60
    text(math.floor(fps), 20, HEIGHT - 50)
    rect(page.l, page.b, page.w, page.h)
    rect(WIDTH / 2 , page.b, page.w, page.h)
    
    ellipseMode(RADIUS)
    
    noFill()
    strokeWidth(2)
    stroke(0)
    ellipse(WIDTH / 2, page.b, page.w)
    ellipse(WIDTH / 2, page.t, vec2(page.w, page.h):len())
    
    fill(255, 0, 0)
    --ellipse(t.tx, t.ty, 25)
    
    fill(0, 0, 255)
    --ellipse(t.x, t.y, 25)
    
    computeCorner()
    
    local t0 = vec2(page.r - t.x, page.b - t.y) * .5 + vec2(t.x, t.y)
    
    fill(0, 255, 0)
    stroke(255, 0, 0)
    
    --text("t0", t0.x, t0.y)
   -- line(t0.x, t0.y, t.x, t.y)
    
    local t2 = vec2(t0.x, page.b)
    
    --text("t2", t2.x, t2.y)
 --   line(t0.x, t0.y, t2.x, t2.y)

    local bTan = math.max(
        t0.x - math.tan(
            math.atan2(page.b - t0.y, page.r - t0.x)) * (page.b - t0.y
        ), 
        WIDTH / 2
    )
    
    local t1 = vec2(bTan, page.b)
    
  --  text("t1", t1.x, t1.y)
--    line(t0.x, t0.y, t1.x, t1.y)
--    line(t1.x, t1.y, t.x, t.y)
    
    local clipAngle = math.atan2(t1.y - t0.y, t1.x - t0.x)
    if clipAngle < 0 then clipAngle = clipAngle + math.pi end
    clipAngle = math.deg(clipAngle - math.pi / 2)
    local pageAngle = math.deg(math.atan2(t1.y - t.y, t1.x - t.x))
    --[[pushMatrix()
        translate(t.x, t.y)
        rotate(pageAngle)
        fill(255, 0, 0, 64)
        rect(0, 0, page.w, page.h)
    popMatrix()
    pushMatrix()
        fill(0, 0, 255, 64)
        translate(t1.x, t1.y)
        rotate(clipAngle)
        rect(-page.w, -100, page.w, page.h + 250)
    popMatrix()]]
    
    -- calculate turned side
    
    --local s1 = t1
    --local s2 = t1 + vec2(0, 1):rotate(clipAngle)
    
    local p1 = vec2(t.x, t.y) + vec2(0, page.h):rotate(math.rad(pageAngle))
    local p2 = p1 + vec2(page.w, 0):rotate(math.rad(pageAngle))
        local a, b = (p1 - vec2(t.x, t.y)), vec2(1, 0)
        local c = vec2(page.r, page.b) - vec2(t.x, t.y)
        local d = c:dot(b) / a:dot(b)
        local p3 = vec2(t.x, t.y) + (p1 - vec2(t.x, t.y)) * d
        
        local a, b = p2 - p1, vec2(0, 1)
        local c = vec2(page.r, page.t) - p1
        local d = c:dot(b) / a:dot(b)
        local p4 = p1 + (p2 - p1) * d
    
    local a, b  = 
    fill(255, 0, 0, 255)
    --[[ellipse(t1.x, t1.y, 10)
    ellipse(t.x, t.y, 10)
    ellipse(p1.x, p1.y, 10)
    ellipse(p2.x, p2.y, 10)
    ellipse(p3.x, p3.y, 10)
    ellipse(p4.x, p4.y, 10)]]
    if p1.x < page.r then
        points = { t1, vec2(t.x, t.y), p1, p4 }
    else
        points = { t1, vec2(t.x, t.y), p3 }
    end 
    flip.vertices = triangulate(points)
    --fill(0,((t.x - page.l) / page.w) * 255)
    fill(255, 0, 0, 138)
    flip:draw()
    -- purple bit is the backside of turned page
end

function touched(touch)
    if touch.state ~= ENDED then
        t.tx = touch.x
        t.ty = touch.y
    else
        if touch.deltaX < 0 or t.x < WIDTH / 2 then
            t.tx, t.ty = page.l, page.b
        else
            t.tx, t.ty = page.r, page.b
        end
    end
end

function computeCorner()
    t.x = t.x + (t.tx - t.x) * 0.13
    t.y = t.y + (t.ty - t.y) * 0.13
    local bDist = vec2(t.x, t.y) - vec2(WIDTH / 2, page.b)
    if bDist:len() > page.w then
        bDist = bDist:normalize() * page.w
        t.x, t.y = WIDTH / 2 + bDist.x, page.b + bDist.y
    end
    local tDist = vec2(t.x, t.y) - vec2(WIDTH / 2, page.t)
    if tDist:len() > vec2(page.w, page.h):len() then
        tDist = tDist:normalize() * vec2(page.w, page.h):len()
        t.x, t.y = WIDTH / 2 + tDist.x, page.t + tDist.y
    end
end

Thanks!
Jordan

Amazing @jordan . This Is great