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){
}