计算机图形学4——Two-Dimensional Transformation(二维几何变换)
实现二维坐标变换矩阵(平移,旋转,缩放)的生成
环境:Code::Blocks 17.12
完整代码如下:
// ====== Computer Graphics Experiment #5 ======
// | Two-Dimensional Transformation |
// =============================================
//
// Requirement:
// (1) Implement functions to generate 2D transformation matrix.
// (2) Implement function to transform 2D point using
// transformation matrix.
// (3) Implement functions to rotate, scale and translate objects
// using keyboard.
#include <windows.h>
#include <GL/glut.h>//记得要配置GLUT库
#include <math.h>
#define pi 3.1415926535
// 2D point class
class CPoint2D
{
public:
float x, y;
};
// 2D transformation matrix
float My2DMatrix[3][3];
// Generate translation matrix
void TranslationMatrix(float tx, float ty, float M[3][3])
// tx, ty --- Translation vector
{
M[0][0]=1.0; M[0][1]=0.0; M[0][2]=tx;
M[1][0]=0.0; M[1][1]=1.0; M[1][2]=ty;
M[2][0]=0.0; M[2][1]=0.0; M[2][2]=1.0;
}
// Generate rotation matrix
void RotationMatrix(float theta, float M[3][3])
// theta --- Rotation angle in degree
{
M[0][0]=cos(theta); M[0][1]=-sin(theta); M[0][2]=0;
M[1][0]=sin(theta); M[1][1]=cos(theta); M[1][2]=0;
M[2][0]=0.0; M[2][1]=0.0; M[2][2]=1.0;
}
// Generate scaling matrix
void ScalingMatrix(float sx, float sy, float M[3][3])
// sx, sy --- Scaling factors
{
M[0][0]=sx; M[0][1]=0.0; M[0][2]=0;
M[1][0]=0.0; M[1][1]=sy; M[1][2]=0;
M[2][0]=0.0; M[2][1]=0.0; M[2][2]=1.0;
}
// Translate
void Translate(float tx, float ty)
// tx, ty --- Translation vector
{
float M[3][3];
//T[0][0]=0.0; T[0][1]=0.0; T[0][2]=0.0;
//T[1][0]=0.0; T[1][1]=0.0; T[1][2]=0.0;
//T[2][0]=0.0; T[2][1]=0.0; T[2][2]=0.0;
TranslationMatrix(tx, ty, M);
float T[3][3];
memset(T,0,sizeof(T));
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
{
T[i][j]+=M[i][k]*My2DMatrix[k][j];
}
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
{
My2DMatrix[i][j]=T[i][j];
}
}
// Rotate
void Rotate(float theta)
// theta --- Rotation angle in degree
{
float M[3][3];
RotationMatrix(theta,M);
float T[3][3];
memset(T,0,sizeof(T));
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
{
T[i][j]+=M[i][k]*My2DMatrix[k][j];
}
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
{
My2DMatrix[i][j]=T[i][j];
}
// Write your code here
// Multiply M to the left of My2DMatrix
}
// Scale
void Scale(float sx, float sy)
// sx, sy --- Scaling factors
{
float M[3][3];
ScalingMatrix(sx, sy, M);
float T[3][3];
memset(T,0,sizeof(T));
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
{
T[i][j]+=M[i][k]*My2DMatrix[k][j];
}
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
{
My2DMatrix[i][j]=T[i][j];
}
}
// Transform 2D point
void Transform2DPoint(CPoint2D *p, float M[3][3], CPoint2D *q)
// p --- Input point
// M --- Transformation matrix
// q --- Output point
{
q->x=M[0][0]*p->x+M[0][1]*p->y+M[0][2];
q->y=M[1][0]*p->x+M[1][1]*p->y+M[1][2];
}
void IdentityMatrix(float M[3][3])
{
M[0][0]=1.0; M[0][1]=0.0; M[0][2]=0.0;
M[1][0]=0.0; M[1][1]=1.0; M[1][2]=0.0;
M[2][0]=0.0; M[2][1]=0.0; M[2][2]=1.0;
}
// Initialization function
void init(void)
{
glClearColor (0.0, 0.0, 0.5, 0.0);
IdentityMatrix(My2DMatrix);
}
// Display callback function
void display(void)
{
static CPoint2D MyObject[]=
{{0.0, 63.0},
{-60.0, 20.0}, {-60.0, -20.0},
{60.0, -20.0}, {60.0, 20.0}};
CPoint2D pp;
int i;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
for (i=0; i<5; ++i)
{
Transform2DPoint(MyObject+i, My2DMatrix, &pp);
glVertex2f(pp.x, pp.y);
}
glEnd();
glutSwapBuffers();
}
// Reshape callback function
void reshape(int w, int h)
{
glViewport (0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-100, 100, -100, 100);
}
// Keyboard callback function
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27: exit(0);
case '+':
Scale(1.5,1.5);glutPostRedisplay();
break;
case '-':
Scale(0.75,0.75);glutPostRedisplay();
break;
}
}
// Special keyboard callback function
void special_key(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_LEFT:
Translate(-5.0, 0.0);glutPostRedisplay();
break;
case GLUT_KEY_RIGHT:
Translate(5.0, 0.0);glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
Translate(0.0, -5.0);glutPostRedisplay();
break;
case GLUT_KEY_UP:
Translate(0.0, 5.0);glutPostRedisplay();
break;
// Add your code for rotation and scaling
case GLUT_KEY_PAGE_UP:
Scale(2,2);glutPostRedisplay();
break;
case GLUT_KEY_PAGE_DOWN:
Scale(0.5,0.5);glutPostRedisplay();
break;
case GLUT_KEY_HOME:
Rotate(pi/2);glutPostRedisplay();
break;
case GLUT_KEY_END:
Rotate(-pi/2);glutPostRedisplay();
break;
case GLUT_KEY_INSERT:
Rotate(pi);glutPostRedisplay();
break;
}
}
// Main program entrance
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow ("Test 2D Transformation");
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutSpecialFunc(special_key);
glutMainLoop();
return 0;
}