计算机图形与OpenGL学习五(二维几何变换2.矩阵表示和齐次坐标)

矩阵表示和齐次坐标

本节矩阵变换公式较多,为方便,设置为图片格式,但实例代码可复制,这样不影响学习,如果需要word版,请私聊。为方便阅读,图片水印加到了最右下角,但是个人劳动成果,未经过同意,请勿转载








【实例】

对象为三角形,平移量(tx,ty)=(0,100);缩放量(sx,xy)=(0.5,0.5);旋转角theta=pi/2;缩放固定点fixedPt、旋转基点pivPt为三角形中心点。

#include<GL/glut.h>
#include<math.h>
#include<Windows.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
GLsizei winWidth = 600, winHeight = 600;
GLuint regHex;//显示表标识
/*设置世界坐标范围*/
GLfloat xwcMin = 0.0, xwcMax = 225.0;
GLfloat ywcMin = 0.0, ywcMax = 225.0;
class wcPt2D
{
public:
	GLfloat x, y;
	
};
typedef GLfloat Matrix3x3[3][3];
Matrix3x3 matComposite;//2D变换复合矩阵
const GLdouble pi = 3.14159;

static void init(void)
{
	//初始化函数,并加入表

	glClearColor(1.0, 1.0, 1.0, 0.0);//设置为白色背景
	

}

void Matrix3x3SetIdentity(Matrix3x3 matIdent3x3)
{
	//生成一个单位矩阵
	GLint row, col;
	for (row = 0; row < 3;++row)
	for (col = 0; col < 3;++col)
	{
		matIdent3x3[row][col] = (row==col);
	}
}
void matrix3x3Premultiply(Matrix3x3 m1, Matrix3x3 m2)
{
   //矩阵的乘法,结果储存在M2中
	GLint row, col;
	Matrix3x3 matTemp;
	for (row = 0; row < 3; ++row)
	for (col = 0; col < 3; col++)
	{
		matTemp[row][col] = m1[row][0] * m2[0][col] + m1[row][1] * m2[1][col] + m1[row][2] * m2[2][col];
	}
	for (row = 0; row < 3; ++row)
	for (col = 0; col < 3; col++)
	{
		m2[row][col] = matTemp[row][col];
	}
	
}
void translate2D(GLfloat tx, GLfloat ty)
{
	/*通过偏移量tx,ty产生平移矩阵matTransl之后,再通过矩阵的乘法,实现对象的平移*/
	Matrix3x3 matTransl;//平移矩阵
	Matrix3x3SetIdentity(matTransl);
	matTransl[0][2] = tx;
	matTransl[1][2] = ty;
	/*矩阵乘法,平移*/
	matrix3x3Premultiply(matTransl,matComposite);
}
void rotate2d(wcPt2D pivotPt, GLfloat theta)
{
	//基准点pivotPt,旋转角度theta,产生旋转矩阵后相乘
	Matrix3x3 matRot;//旋转矩阵
	Matrix3x3SetIdentity(matRot);
	matRot[0][0] = cos(theta);
	matRot[0][1] = -sin(theta);
	matRot[0][2] = pivotPt.x*(1 - cos(theta)) + pivotPt.y*sin(theta);
	matRot[1][0] = sin(theta);
	matRot[1][1] = cos(theta);
	matRot[1][2] = pivotPt.y*(1 - cos(theta)) - pivotPt.x*sin(theta);
	/*矩阵乘法,旋转*/
	matrix3x3Premultiply(matRot, matComposite);

}
void scale2D(GLfloat sx, GLfloat sy, wcPt2D fixedPt)
{
	//固定点fixedPt,缩放系数sx,sy,产生缩放矩阵
	Matrix3x3 matScale;
	Matrix3x3SetIdentity(matScale);
	matScale[0][0] = sx;
	matScale[0][2] = (1 - sx)*fixedPt.x;
	matScale[1][1] = sy;
	matScale[1][2] = (1 - sy)*fixedPt.y;
	matrix3x3Premultiply(matScale, matComposite);
	
}
void translate2D(GLint nverts, wcPt2D *verts)
{
   //对象顶点与复合变换矩阵的乘法,得到坐标变换后的点
	GLint k;
	GLfloat temp;
	for (k = 0; k < nverts; ++k)
	{
		temp = verts[k].x*matComposite[0][0] + verts[k].y*matComposite[0][1] + matComposite[0][2];
		verts[k].y = verts[k].x*matComposite[1][0] + verts[k].y*matComposite[1][1] + matComposite[1][2];
		verts[k].x = temp;
	}
}
void triangle(wcPt2D *verts)
{
	//输出一个三角形
	GLint k;
	glBegin(GL_TRIANGLES);
	cout << "当前顶点坐标为:";
	for (k = 0; k < 3; ++k)
	{
		glVertex2f(verts[k].x,verts[k].y);
		cout << verts[k].x << ","<< verts[k].y << endl;
	}
	glEnd();

}
void displayFcn()
{
	GLint nverts = 3;
	wcPt2D verts[3] = { { 50.0, 25.0 }, { 150.0, 25.0 }, {100.0,100.0} };//定义一个三角形
	wcPt2D centroidPt;//中点坐标顶点对象
	GLint k, xSum = 0, ySum = 0;//xSum,ySum用于计算中点坐标,作为基点
	for (k = 0; k < nverts; ++k)
	{
		xSum += verts[k].x;
		ySum += verts[k].y;
	}
	centroidPt.x = GLfloat(xSum )/ GLfloat(nverts);
	centroidPt.y = GLfloat(ySum) / GLfloat(nverts);
	wcPt2D pivPt, fixedPt;//旋转基点,缩放固定点
	pivPt = centroidPt;
	fixedPt =centroidPt;
	GLfloat tx = 0.0, ty = 100.0;
	GLfloat sx = 0.5, sy = 0.5;
	GLdouble theta = pi / 2.0;
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(0.0, 0.0, 1.0);
	triangle(verts);//蓝色三角形为原始三角形
	Matrix3x3SetIdentity(matComposite);
	scale2D(sx, sy, fixedPt);//缩放
	rotate2d(pivPt, theta);//旋转
	translate2D(tx, ty);//移动
	translate2D(nverts, verts);
	glColor3f(1.0, 0.0, 0.0);//红色为移动后的三角形
	triangle(verts);
	glFlush();


}
void winReshapeFcn(int newWidth, int newHeight)
{
	//窗口重定形函数
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();//将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作
	gluOrtho2D(xwcMin,xwcMax, ywcMin, ywcMax);
	glClear(GL_COLOR_BUFFER_BIT);


} int main(int argc, char**argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowPosition(50, 50);
	glutInitWindowSize(winWidth, winHeight);
	glutCreateWindow("Example");
	init();
	glutDisplayFunc(displayFcn);
	glutReshapeFunc(winReshapeFcn);
	glutMainLoop();
	return 0;
}
结果:

猜你喜欢

转载自blog.csdn.net/lhs322/article/details/79929887
今日推荐