I wrote a program to simulate a simple page flip animation in opengl and now i'm trying to replicate it with two images using texture mapping so that the second image appears on the "back" of the first image during the drag of the lower left corner of the page. However, i can't get figure out the correct assingment of texture coordinates. The two functions in question are below and I would appreciate it if anyone has any useful pointer.
The extra float variables are used to set the values of the coordinates to the proper range of (0, 1) since the length of the window is 256x256 and there's 40px padding on all sides making the image 176x176.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// lowerRightCorner1:
//
// Draw folded triangle or quadrilateral when lower right corner is
// pulled ABOVE lower edge of page.
//
static void
drawLowerRightCorner1(int x, int y)
{
float bottom[2], right[2], top[2], corner[2];
// clear color and depth buffer to background values
glClear(GL_COLOR_BUFFER_BIT);
// init page dimensions
int w = W - 2*Margin;
int h = H - 2*Margin;
// flag default case: folded triangle at corner
int triangle = 1;
// clip x
if(x > W-Margin) x = W-Margin;
// distance between (x,y) and page boundary
int dx = (W-Margin) - x;
int dy = (H-Margin) - y;
double len = sqrt(double((x-Margin)*(x-Margin) + dy*dy));
if(dy < 0 || len >= w) return;
// ____
// \dx|
// b \ | a Lifted folded triangle above bottom right corner
// \|
//
// Note: a + b = dy (distance from top of triangle to bottom paper edge)
// Plug a = dy - b into:
// dx^2 + a^2 = b^2
// Solve for b to get:
// b = (dx^2 + dy^2) / 2dy
//
double b = (dx*dx + dy*dy) / (2*dy);
double a = dy - b;
// eval intersection on right and bottom edges
bottom[0] = x - a*dy/dx;
bottom[1] = H-Margin;
right [0] = W-Margin;
right [1] = y + a;
// error checking: avoid tearing bottom edge of paper from spine
if(bottom[0] < Margin) {
bottom[0] = Margin; // clamp bottom x to spine
x = (int) sqrt(double(w*w - dy*dy)); // adjust lifted corner position
x += Margin; // add back the Margin pixels
}
// error checking: lifted quadrilateral, not triangle
if(right[1] < Margin) {
// flag quadrilateral case
triangle = 0;
// eval position of lifted top right corner
double d = sqrt(dx*dx + a*a);
corner[0] = x + (h * dx/d);
corner[1] = y + (h * a/d);
top[0] = corner[0] + ((corner[1]-Margin) * a/dx);
top[1] = Margin;
}
float bottom0 = bottom[0]/256;
float bottom1 = bottom[1]/256;
float right0 = right[0]/256;
float right1 = right[1]/256;
// draw page outline
if(triangle) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TexId1);
// draw main polygon
glBegin(GL_POLYGON);
// draw bottom left, upper left, and upper right corners
glTexCoord2f(0, 1); glVertex2f(Margin, H-Margin);
glTexCoord2f(0, 0); glVertex2f(Margin, Margin);
glTexCoord2f(1, 0); glVertex2f(W-Margin, Margin);
//glTexCoord2f(1, 1); glVertex2f(W-Margin, H-Margin);
//cout << "w-margin: "<<W-Margin<<" h-margin: "<<H-Margin<<"\n";
//cout << "right0: "<<right0<<" right1: "<<right1<<"\n";
//cout << "bottom0: "<<bottom0<<" bottom1: "<<bottom1<<"\n";
// xsect at right edge
glTexCoord2f(right0, right1); glVertex2f(right[0], right[1]);
// xsect at bottom edge
glTexCoord2f(bottom0, bottom1); glVertex2f(bottom[0], bottom[1]);
glEnd();
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TexId2);
// draw lifted triangle
glBegin(GL_POLYGON);
glTexCoord2f(0,1); glVertex2f(x, y); // lifted corner point
// xsect at right edge
glTexCoord2f(right0, right1); glVertex2f(right[0], right[1]);
// xsect at bottom edge
glTexCoord2f(bottom0, bottom1); glVertex2f(bottom[0], bottom[1]);
glEnd();
glDisable(GL_TEXTURE_2D);
} else {
float top0 = top[0]/256;
float top1 = top[1]/256;
float corner0 = corner[0]/256;
float corner1 = corner[1]/256;
//cout << "top0: "<<top0<<" top1: "<<top1<<"\n";
//cout << "bottom0: "<<bottom0<<" bottom1: "<<bottom1<<"\n";
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TexId1);
// draw main polygon
glBegin(GL_POLYGON);
// draw bottom left and upper left corners
glTexCoord2f(0, 1); glVertex2f(Margin, H-Margin);
glTexCoord2f(0, 0); glVertex2f(Margin, Margin);
// xsect at top edge
glTexCoord2f(top0, top1); glVertex2f(top[0], top[1]);
// xsect at bottom edge
glTexCoord2f(bottom0, bottom1); glVertex2f(bottom[0], bottom[1]);
glEnd();
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TexId2);
// draw lifted quadrilateral
glBegin(GL_POLYGON);
// draw lifted corner point and next lifted corner
glTexCoord2f(1, 1); glVertex2f(x, y);
glTexCoord2f(corner0, corner1); glVertex2f(corner0, corner1);
// xsect at right edge
glTexCoord2f(top0, top1); glVertex2f(top0, top1);
// xsect at bottom edge
glTexCoord2f(bottom0, bottom1); glVertex2f(bottom0, bottom1);
glEnd();
glDisable(GL_TEXTURE_2D);
}
// flush to display
glutSwapBuffers();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// lowerRightCorner2:
//
// Draw folded quadrilateral when lower right corner is
// pulled BELOW lower edge of page.
//
static void
drawLowerRightCorner2(int x, int y)
{
float bottom[2], right[2], top[2], corner[2];
// clear color and depth buffer to background values
glClear(GL_COLOR_BUFFER_BIT);
// init page dimensions
int w = W - 2*Margin;
int h = H - 2*Margin;
// clip x
if(x > W-Margin) x = W-Margin;
// distance between (x,y) and page boundary
float dx = (W-Margin) - x;
float dy = (H-Margin) - y;
double len = sqrt((x-Margin)*(x-Margin) + dy*dy);
if(dy > 0 || len >= w) return;
// a
// ____
// | /
// dy | / b Lifted folded triangle below bottom right corner
// |/
//
// Note: a + b = dx (distance from left of triangle to right paper edge)
// Plug a = dx - b into:
// dy^2 + a^2 = b^2
// Solve for b to get:
// b = (dx^2 + dy^2) / 2dx
//
double b = (dx*dx + dy*dy) / (2*dx);
double a = dx - b;
// eval intersection on bottom edge
bottom[0] = x + a;
bottom[1] = H-Margin;
// eval position of lifted top right corner
double d = sqrt(dx*dx + a*a);
corner[0] = x + (dy/b * h);
corner[1] = y - (a/b * h);
dx = (W-Margin) - corner[0];
dy = corner[1] - Margin;
b = (dx*dx + dy*dy) / (2*dx);
a = dx - b;
// eval position of lifted top left corner
top[0] = corner[0] + a;
top[1] = Margin;
// error checking: avoid tearing top edge of paper from spine
if(top[0] < Margin) {
corner[0] += (Margin-top[0]); // reset lifted corner
top[0] = Margin; // clamp top x to spine
}
//error checking for stretching
if(corner[1] > W-Margin) return;
float bottom0 = bottom[0]/256;
float bottom1 = bottom[1]/256;
float top0 = top[0]/256;
float top1 = top[1]/256;
float corner0 = corner[0]/256;
float corner1 = corner[1]/256;
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TexId1);
// draw page outline
glBegin(GL_POLYGON);
// draw bottom left / upper left corners, and top / bottom xsects
glTexCoord2f(0, 1); glVertex2f(Margin, H-Margin);
glTexCoord2f(0, 0); glVertex2f(Margin, Margin);
glTexCoord2f(top0, top1); glVertex2f(top[0], top[1]);
glTexCoord2f(bottom0, bottom1); glVertex2f(bottom[0], bottom[1]);
glEnd();
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, TexId2);
// draw lifted quadrilateral
glBegin(GL_POLYGON);
// draw lifted corner point and next lifted corner
glTexCoord2f(1, 1);glVertex2f(x, y);
glTexCoord2f(corner0, corner1); glVertex2f(corner[0], corner[1]);
// xsect at top edge
glTexCoord2f(top0, top1); glVertex2f(top[0], top[1]);
// xsect at bottom edge
glTexCoord2f(bottom0, bottom1); glVertex2f(bottom[0], bottom[1]);
glEnd();
glDisable(GL_TEXTURE_2D);
// flush to display
glutSwapBuffers();
}