S(-1,1) is a reflection about the Y-axis.
Many answers possible; one is T(-1,1) o H(X,0.5) o S(1.5/sqrt2,2/sqrt2) o R(135°) o T(2,0).
gluPerspective(90, 1, 2, 10) means L = B = -2, R = T = 2, N = 2, F = 10.
+- -+ +- -+ +- -+
|1 0 0 0| | 2 3| | 2 3|
|0 1 0 0| | 0 3| = | 0 3|
|0 0 -1.5 -5| |-5 4| |2.5 -11|
|0 0 -1 0| | 1 1| | 5 -4|
+- -+ +- -+ +- -+
Therefore
(2, 0, -5) --> (.4, 0, .5)
(3, 3, 4) --> (-.75, -.75, 2.75)
What is fascinating about this is that Q was IN FRONT OF the frustum in world coordinates, but in NDCs, it IS BEHIND the view volume! This is why we don't clip in NDCs. Try drawing the projection of line PQ in NDCs. Note that it is **not** the same as PndcQndc.
For the line passing through (1,4,-3) and (-2,1,7), there are many possible representations, but the most obvious one is λu. (1-3u, 4-3u, -3+10u).
R(-82°)(7,8) = (8.9, -5.8)
All points have to project to the near clipping plane, when the distance from the eye point to the near clipping plane is 0, all points project to a single point. You can see this by noting that in the projection matrix
+-- --+
| 2N/(R-L) 0 (R+L)/(R-L) 0 |
| 0 2N/(T-B) (T+B)/(T-B) 0 |
| 0 0 (F+N)/(F-N) 2FN/(F-N) |
| 0 0 -1 0 |
+-- --+
setting n to 0 produces the transformation matrix
+-- --+
| 0 0 (R+L)/(R-L) 0 |
| 0 0 (T+B)/(T-B) 0 |
| 0 0 1 0 |
| 0 0 -1 0 |
+-- --+
from which you can see that the transformation of any point (x,y,z) is ((R+L)/(L-R), (T+B)/(B-T), -1). Note that EVERY point in world coordinates transforms to this single point in NDC.
I don't know about this one. I don't even know if it is decidable.
Here's my short program to do this:
/*****************************************************************************
*
* nonaffine.cpp
*
* This program is an example of applying a nonaffine transformation to a
* polygon.
*
*****************************************************************************/
#include <GL/glut.h>
// Here is a little Point class for 2-D points. It features a neat little
// member function which will return a point on the line from the point object
// to an endpoint, given a u-value. u=0 will return the point object itself,
// u=1 will return the endpoint, u=0.5 will return the midpoint of the point
// and the endpoint, etc.
class Point {
public:
double x, y;
Point(double x, double y): x(x), y(y) {}
Point onLine(Point end, double u) {
return Point(x + u*(end.x-x), y + u*(end.y-y));
}
};
// This is the polygon that we have to transform.
Point myPolygon[] = {
Point(-0.4, -0.4),
Point(0.7, -0.4),
Point(0.7, 0.2),
Point(0.15, 1.0),
Point(-0.4, 0.2)
};
// This is the transformation we have to apply.
Point transform(Point p) {
return Point(p.x/2 + p.x*p.x/1.8 + p.y/5 + 0.3, p.y/2 + p.x*p.y/1.7 + 0.3);
}
// reshape() fixes up the projection matrix so that we dont introduce any
// distortion when the window is not square. We want the window to range from
// -1.5 .. 1.5 in the shortest direction.
void reshape(GLint w, GLint h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double aspect = (GLdouble)w / (GLdouble)h;
if (w <= h) gluOrtho2D(-1.5, 1.5, -1.5 / aspect, 1.5 / aspect);
else gluOrtho2D(-1.5 * aspect, 1.5 * aspect, -1.5, 1.5);
glMatrixMode(GL_MODELVIEW);
}
// Clears the window, draws coordinate axes, the original polygon,
// and the transformed polygon. Note: this is very inefficient.
// The polygon and the transformed polygon should be put into
// display lists.
void display() {
glClear(GL_COLOR_BUFFER_BIT);
// Draw coordinate axes in white.
glColor3f(1, 1, 1);
glBegin(GL_LINES);
glVertex2f(-10, 0); glVertex2f(10, 0);
glVertex2f(0, -10); glVertex2f(0, 10);
glEnd();
// Draw the original polygon in blue.
glColor3f(0, 0, 1);
int numVertices = sizeof myPolygon / sizeof(Point);
glBegin(GL_POLYGON);
for (int i = 0; i < numVertices; i++)
glVertex2dv((double*)&myPolygon[i]);
glEnd();
// Draw the transformed polygon in yellow.
glColor3f(1, 1, 0);
glBegin(GL_LINE_STRIP);
for (int j = 0; j < numVertices; j++) {
Point start = myPolygon[j];
Point end = myPolygon[(j + 1) % numVertices];
for (double u = 0.0; u <= 1.0; u += 0.001) {
Point nextPoint = transform(start.onLine(end, u));
glVertex2dv((double*)&nextPoint);
}
}
glEnd();
glFlush();
}
// The usual main() for GLUT.
void main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("Nonaffine Transformation Example");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
}
D(a) = ln 4 / ln(2 cos(a) + 2)