Rick Barraza's page turn

Hi all,

I am trying to convert Rick Barraza’s page turn code from here: http://rbarraza.com/html5-canvas-pageflip/ to OF.

I’ve got most of the way but am a little bit stuck on the masking/clipping part. I’ve been trying to use the masking method from here: http://openframeworks.cc/learning/02_graphics/how_to_maskanimagewithashape/ but no matter what I do, I just can’t seem to get it right.

Can anyone help (code below)?

ofApp.h:

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{
    public:
    void setup();
    void update();
    void draw();
	
    void keyPressed(int key);
    void keyReleased(int key);
    void mouseMoved(int x, int y);
    void mouseDragged(int x, int y, int button);
    void mousePressed(int x, int y, int button);
    void mouseReleased(int x, int y, int button);
    void mouseEntered(int x, int y);
    void mouseExited(int x, int y);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);

    void startTurn();

    int width;
    int height;
    int pageWidth;
    int pageHeight;
    float innerRadius;
    float outerRadius;

    ofPoint spineTop;
    ofPoint spineBottom;
    ofPoint mousePos;
    ofPoint mouseFollow;
    ofPoint pageCorner;
    ofPoint bottomRightEdge;
    ofPoint bottomLeftEdge;
    ofPoint bisector;
    ofPoint tangentBottom;
    ofPoint bisectorBottom;
    float bisectorAngle;
    float bisectorTangent;

    float pageAngle;
    float clipAngle;
    float imgAngle;
    float clipOverflow;
    float clipWidth;
    float clipHeight;
    float clipX;
    float clipY;

    ofPath path;
    ofFbo fbo;
    ofFbo fbo2;
    ofImage img;

    ofPoint rotateClipPoint(ofPoint _p, float angle);

    bool isDrag;
    bool isTurning;
    bool isMouseOver;
    bool isMouseDown;

    bool draggingRTL;
};

ofApp.cpp
#include “ofApp.h”

//--------------------------------------------------------------
void ofApp::setup(){
    width = 600;
    height = 300;
    pageWidth = width * 0.5;
    pageHeight = height;
    innerRadius = pageWidth;
    outerRadius = sqrt(pageWidth * pageWidth + pageHeight * pageHeight);
    
    spineTop.x = pageWidth;
    spineTop.y = 0;
    spineBottom.x = pageWidth;
    spineBottom.y = pageHeight;
    bottomRightEdge.x = width;
    bottomRightEdge.y = pageHeight;
    bottomLeftEdge.x = 0;
    bottomLeftEdge.y = pageHeight;
    
    clipOverflow = 50;
    clipWidth = pageWidth * 2;
    clipHeight = pageHeight + (clipOverflow * 2);
    
    fbo.allocate(clipWidth, clipHeight, GL_RGBA);
    fbo.begin();
    ofClear(0,0,0,0);
    fbo.end();
    
    img.load("test.jpg");
    
    draggingRTL = false;
    isMouseOver = false;
    isMouseDown = false;
    isDrag = false;
    isTurning = false;
    mousePos.x = bottomRightEdge.x - 1;
    mousePos.y = bottomRightEdge.y - 1;
}

//--------------------------------------------------------------
void ofApp::update(){
    
    mouseFollow.x += (mousePos.x - mouseFollow.x) * 0.13;
    mouseFollow.y += (mousePos.y - mouseFollow.y) * 0.13;
    
    float dx = spineBottom.x - mouseFollow.x;
    float dy = spineBottom.y - mouseFollow.y;
    
    ofPoint radius1;
    ofPoint radius2;
    
    float angle2follow = atan2(dy, dx);
    radius1.x = spineBottom.x - cos(angle2follow) * innerRadius;
    radius1.y = spineBottom.y - sin(angle2follow) * innerRadius;
    
    float distanceFromTop = sqrt( ( dy * dy ) + ( dx * dx ) );
    if ( distanceFromTop > innerRadius)
    {
        pageCorner.x = radius1.x;
        pageCorner.y = radius1.y;
        
    } else {
        
        pageCorner.x = mouseFollow.x;
        pageCorner.y = mouseFollow.y;
        
    }
    
    
    // WHAT DIRECTION FROM THE SPINE TOP IS THE CORNER
    dx = spineTop.x - pageCorner.x;
    dy = spineTop.y - pageCorner.y;
    angle2follow = atan2(dy, dx);
    
    // USING THE ABOVE, VISUALIZE THE OUTER RADIUS CONSTRAINT
    radius2.x = spineTop.x - cos(angle2follow) * outerRadius;
    radius2.y = spineTop.y - sin(angle2follow) * outerRadius;
    
    // CONSTRAINT THE CORNER [C] TO THE OUTER RADIUS [R2] IF IT FALLS OUTSIDE IT
    float distanceToCorner = sqrt(dx * dx + dy * dy);
    if ( distanceToCorner > outerRadius )
    {
        pageCorner.x = radius2.x;
        pageCorner.y = radius2.y;
    }
    
    if(draggingRTL)
    {
        
    bisector.x = pageCorner.x + .5 * (bottomRightEdge.x - pageCorner.x);
    bisector.y = pageCorner.y + .5 * (bottomRightEdge.y - pageCorner.y);
    
    bisectorAngle = atan2(bottomRightEdge.y - bisector.y, bottomRightEdge.x - bisector.x);
    bisectorTangent = bisector.x - tan(bisectorAngle) * (bottomRightEdge.y - bisector.y);
        
    }else{
        
        bisector.x = pageCorner.x + .5 * (bottomLeftEdge.x - pageCorner.x);
        bisector.y = pageCorner.y + .5 * (bottomLeftEdge.y - pageCorner.y);
        
        bisectorAngle = atan2(bottomLeftEdge.y - bisector.y, bottomLeftEdge.x - bisector.x);
        bisectorTangent = bisector.x - tan(bisectorAngle) * (bottomLeftEdge.y - bisector.y);
    }
    
    
    if (bisectorTangent < 0)
    {
        bisectorTangent = 0;
    }
    
    tangentBottom.x = bisectorTangent;
    tangentBottom.y = bottomRightEdge.y;
    
    bisectorBottom.x = bisector.x;
    bisectorBottom.y = tangentBottom.y;

    if(draggingRTL)
    {
        pageAngle = atan2(tangentBottom.y - pageCorner.y, tangentBottom.x - pageCorner.x);
        
    }
    else
    {
        pageAngle = PI + atan2(tangentBottom.y - pageCorner.y, tangentBottom.x - pageCorner.x);
    }
    

    clipAngle = atan2(tangentBottom.y - bisector.y, tangentBottom.x - bisector.x);
    if ( clipAngle < 0 ){
        clipAngle += PI;
    }
    clipAngle -= PI/2;
    
    imgAngle = clipAngle - pageAngle;
    
    
}

//--------------------------------------------------------------
void ofApp::draw(){
    
    ofSetColor(255);
    ofDrawRectangle(0, 0, width, height);
    
    ofSetColor(255,0,0,100);
    ofDrawRectangle(0, 0, pageWidth, pageHeight);
    
    ofSetColor(0,0,255,100);
    ofDrawRectangle(pageWidth, 0, pageWidth, pageHeight);
    
    ofSetColor(0);
    ofNoFill();
    ofDrawCircle(spineBottom.x, spineBottom.y, innerRadius);
    ofDrawCircle(spineTop.x, spineTop.y, outerRadius);
    
    float dx = spineBottom.x - mouseFollow.x;
    float dy = spineBottom.y - mouseFollow.y;
    
    ofPoint radius1;
    float angle2follow = atan2(dy, dx);
    radius1.x = spineBottom.x - cos(angle2follow) * innerRadius;
    radius1.y = spineBottom.y - sin(angle2follow) * innerRadius;
    
    ofDrawCircle(radius1.x, radius1.y, 10);
    
    ofFill();
    ofDrawCircle(mousePos.x, mousePos.y, 3);
    
    ofSetColor(255,0,0);
    ofDrawCircle(pageCorner.x, pageCorner.y, 3);
    
    ofDrawCircle(bisector.x, bisector.y, 3);
    
    ofDrawCircle(bottomRightEdge.x, bottomRightEdge.y, 3);
    ofDrawCircle(bottomLeftEdge.x, bottomLeftEdge.y, 3);
    
    
    
    ofDrawLine(spineBottom.x, spineBottom.y, pageCorner.x, pageCorner.y );
    ofDrawLine(spineTop.x, spineTop.y, pageCorner.x, pageCorner.y );
    
    if(draggingRTL)
    {
        ofDrawLine(bottomRightEdge.x, bottomRightEdge.y, pageCorner.x, pageCorner.y );
    }
    else
    {
        ofDrawLine(bottomLeftEdge.x, bottomLeftEdge.y, pageCorner.x, pageCorner.y);
    }
    
    
    ofDrawLine(bisector.x, bisector.y, tangentBottom.x, tangentBottom.y);
    ofDrawLine(bisector.x, bisector.y, bisectorBottom.x, bisectorBottom.y);
    ofDrawLine(tangentBottom.x, tangentBottom.y, bisectorBottom.x, bisectorBottom.y);
    ofDrawLine(tangentBottom.x, tangentBottom.y, pageCorner.x, pageCorner.y);

    clipX = tangentBottom.x;
    clipY = tangentBottom.y;
    ofPoint clipPoint0 = rotateClipPoint(ofPoint(clipX, clipY + clipOverflow), clipAngle);
    ofPoint clipPoint1 = rotateClipPoint(ofPoint(clipX - pageWidth, clipY + clipOverflow), clipAngle);
    ofPoint clipPoint2 = rotateClipPoint(ofPoint(clipX - pageWidth, clipY - (pageHeight + clipOverflow)), clipAngle);
    ofPoint clipPoint3 = rotateClipPoint(ofPoint(clipX, clipY - (pageHeight + clipOverflow)), clipAngle);

    
    path.clear();
    path.lineTo(clipPoint2);
    path.lineTo(clipPoint3);
    path.lineTo(clipPoint0);
    path.lineTo(clipPoint1);
    
    ofSetColor(255,255,255,255);
    fbo.begin();
    ofClear(0,0,0,0);
    path.draw();
    fbo.end();
    
    img.getTexture().setAlphaMask(fbo.getTexture());
 
    ofPushMatrix();
    ofTranslate(pageCorner.x, pageCorner.y);
    ofRotate(ofRadToDeg(pageAngle));
    img.draw(0, -pageHeight, pageWidth, pageHeight);
    ofPopMatrix();
    

    ofSetColor(0, 255, 0, 100);
    ofPushMatrix();
    ofTranslate(pageCorner.x, pageCorner.y);
    ofRotate(ofRadToDeg(pageAngle));
    if(draggingRTL){
        ofDrawRectangle(0, -pageHeight, pageWidth, pageHeight);
    }else{
        ofDrawRectangle(-2 * (pageWidth * 0.5), -pageHeight, pageWidth, pageHeight);
    }
    ofPopMatrix();
    

    
    
    ofSetColor(0, 0, 255, 100);
    ofDrawCircle(clipPoint0.x, clipPoint0.y, 3);
    ofDrawCircle(clipPoint1.x, clipPoint1.y, 3);
    ofDrawCircle(clipPoint2.x, clipPoint2.y, 3);
    ofDrawCircle(clipPoint3.x, clipPoint3.y, 3);
    ofDrawLine(clipPoint0.x, clipPoint0.y, clipPoint1.x, clipPoint1.y);
    ofDrawLine(clipPoint1.x, clipPoint1.y, clipPoint2.x, clipPoint2.y);
    ofDrawLine(clipPoint2.x, clipPoint2.y, clipPoint3.x, clipPoint3.y);
    ofDrawLine(clipPoint3.x, clipPoint3.y, clipPoint0.x, clipPoint0.y);
    
    ofSetColor(255,255,255,255);
    ofDrawCircle(tangentBottom.x, tangentBottom.y, 3);

}

//--------------------------------------------------------------
ofPoint ofApp::rotateClipPoint(ofPoint _p, float angle) {
    _p.x -= tangentBottom.x;
    _p.y -= tangentBottom.y;
    
    ofPoint result;
    result.x = (_p.x * cos(angle)) - (_p.y * sin(angle) );
    result.y = sin(angle) * _p.x + cos(angle) * _p.y;
    
    result.x += tangentBottom.x;
    result.y += tangentBottom.y;
    
    return result;
}

//--------------------------------------------------------------
void ofApp::startTurn()
{
    mousePos.x = bottomRightEdge.x - pageWidth * 2;
    mousePos.y = bottomRightEdge.y;
    
    //isTurning = true;
    isMouseOver = false;
    isMouseDown = false;
    isDrag = false;
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y){

    
}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
    if ( isTurning ) return;
    
    
    if ( isDrag )
    {
        mousePos.x = mouseX;
        mousePos.y = mouseY;

        if(draggingRTL)
        {
            if ( mousePos.x < ( pageWidth * .25) )
            {
                //startTurn();
            }
        }else
        {
            
        }
        
        
    } else {
        
        mousePos.x = bottomRightEdge.x - 1;
        mousePos.y = bottomRightEdge.y - 1;
        
    }
}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
    
    if ( isTurning ) return;
    
    //if we started dragging from the bottom right corner
    if ( (x > (bottomRightEdge.x - pageWidth * 0.125)) && x < bottomRightEdge.x )
    {
        if ( (y > (bottomRightEdge.y - (pageHeight * 0.5))) && y < bottomRightEdge.y )
        {
            isDrag = true;
            isMouseOver = true;
            draggingRTL = true;
        }
    }
    
    if (x > 0 && x < pageWidth )
    {
        if ( (y > (bottomRightEdge.y - (pageHeight * 0.5))) && y < bottomRightEdge.y )
        {
            isDrag = true;
            isMouseOver = true;
            draggingRTL = false;
        }
    }
}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
    
    if ( isTurning ) return;
    
    //if we go past halfway
    if ( mousePos.x < pageWidth )
    {
        
        startTurn();
        
    } else
    {
        mousePos.x = bottomRightEdge.x - 1;
        mousePos.y = bottomRightEdge.y - 1;
    }
    
    isMouseOver = false;
    isMouseDown = false;
    isDrag = false;
}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 

}