我是靠谱客的博主 忧郁美女,最近开发中收集的这篇文章主要介绍OpenGL-学习之路-简单二维几何变换及应用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

简单二维几何变换


1. 回顾gluOrtho和glViewport


在OpenGL中,gluOtho和glViewport 为两个比较重要的投影变换函数。

-gluOrtho 是创建一个正交平行的视影体的矩阵,并把它与当前矩阵相乘,裁剪出要显示的部分。例如你画出了一个半径为1,中心点在圆点的二维图形圆形,gluOrtho2D作用在了 (0,1,0,1)。则最终显示了个1/4圆形。

-glViewport 则是定义了像素矩阵,最终图像将映射到该矩阵。例如,上面那个1/4圆形原本是显示在左下角,如果我们将glViewport  定义在(0,1,1,1),则该1/4圆形显示在了窗口的左上角。

简单来说: gluOrtho定义了显示的内容,glVieport则设置了显示的位置。

更详细内容:

http://www.cnblogs.com/yxnchinahlj/archive/2010/10/30/1865298.html

http://blog.csdn.net/lingedeng/article/details/7302204


2. 简单二维几何变换


简单二维几何的变换,可以通过 坐标变换 或 矩阵变换。两个方法各有长处,具体使用看实际情况。

下面是平移,旋转,缩放的简单二维图形变换。


#include <glglut.h>
#include <iostream>
using namespace std;

//transilate时,x,y上的增量
float i = 0,j=0;
//rotate时的角度增量
GLint angle=0;
//scale时,x,y上的增量
float s1 = 1, s2 = 1;

void init()
{
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0.0, 600.0, 0.0, 600.0);
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glTranslatef(300+i, 300+j, 0);
	glRotatef(angle % 360, 0, 0, 1);
	glScalef(s1, s2, 0);

	glColor3f(0, 0.6, 0.5);
	glRectf(-100, 100, 100, -100);

	glFlush();
	glutSwapBuffers();
}

void keyboard(unsigned char key, int x, int y)
{
	switch (key)
	{
	case 'w':
		j++; break;
	case 's':
		j--; break;
	case 'a':
		i--; break;
	case 'd':
		i++; break;
	case 'q':
		angle += 10; break;
	case 'e':
		angle -= 10; break;
	case 'z':
		s1 += 0.1; break;
	case 'x':
		s2 += 0.1; break;
	case 'c':
		s1 -= 0.1; break;
	case 'v':
		s2 -= 0.1; break;
	}
	glutPostRedisplay();
}

void main(int argc, char ** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowPosition(400, 50);
	glutInitWindowSize(600, 600);
	glutCreateWindow("Computer Graphics: 二维几何变换");

	init();

	glutDisplayFunc(display);

	cout << " w,s,a,d键 分别为上下左右平移" << endl;
	cout << " q,e键 分别为放大,缩小" << endl;
	cout << " z,x,c,v键 分别为长宽的放大缩小" << endl;
	glutKeyboardFunc(keyboard);

	glutMainLoop();
}


最后效果:



3. 应用——Sun,Earth,Moon


内容:画出三个圆分别代表,太阳,地球,月球,并且地球绕着太阳旋转,月亮绕着地球旋转。


#include <glglut.h>
#include <math.h>

//旋转角度
GLint angle = 30;
//地球旋转半径
GLdouble r1 = 100;
//月球旋转半径
GLdouble r2 = 40;

void init()
{
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0.0, 600.0, 0.0, 600.0);
}

//画圆函数,传入中心点坐标(x,y),以及半径r
void drawCircle(double x, double y, double r)
{
	double N = 30;
	//把圆N等分,则每一等分为 360/N=2Pi/N , 则旋转角度为 i*360/N=2*Pi*i/N 
	double delta = 3.1415926*2.0 / N;
	glBegin(GL_TRIANGLE_FAN);
	for (int i = 0; i <= N; i++)
	{
		glVertex2f(x, y);
		glVertex2f(x + r*cos(delta*i), y + r*sin(delta*i));
		glVertex2f(x + r*cos(delta*(i + 1)), y + r*sin(delta*(i + 1)));
	}
	glEnd();
}

//坐标变换
void run()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	//太阳
	glColor3f(1.0f, 0.0f, 0.0f);
	drawCircle(300, 300, 20);

	//地球
	int x0, y0;
	x0 = 300 + r1*cos((3.1415926*2.0 / 360)*(angle % 360));
	y0 = 300 + r1*sin((3.1415926*2.0 / 360)*(angle % 360));
	glColor3f(0.0, 0.5, 1.0);
	drawCircle(x0, y0, 15);

	//月球
	int x1, y1;
	x1 = x0 + r2*cos((3.1415926*2.0 / 360)*(angle * 12 % 360));
	y1 = y0 + r2*sin((3.1415926*2.0 / 360)*(angle * 12 % 360));
	glColor3f(1.0, 1.0, 1.0);
	drawCircle(x1, y1, 5);

	glFlush();
	glutSwapBuffers();
}

//矩阵变换
/*
void run()
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

//太阳
glTranslatef(300.0f, 300.0f, 0.0f);
glColor3f(1.0f, 0.0f, 0.0f);
drawCircle(0, 0, 20);

//地球
glRotatef(angle % 360, 0, 0, 1);
glTranslatef(r1, 0, 0);
glColor3f(0.0f, 0.5f, 1.0f);
drawCircle(0, 0, 15);

//月球
glRotatef(angle * 12 % 360, 0, 0, 1);
glTranslatef(r2, 0, 0);
glColor3f(1.0f, 1.0f, 1.0f);
drawCircle(0, 0, 5);

glFlush();
glutSwapBuffers();
}
*/

void idle()
{
	angle++;
	glutPostRedisplay();
}

void main(int argc, char ** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowPosition(400, 50);
	glutInitWindowSize(600, 600);
	glutCreateWindow("Computer Graphics: Sun,Earth,Moon");

	init();

	glutDisplayFunc(run);
	glutIdleFunc(idle);

	glutMainLoop();
}


最后效果:


4, 应用——简单自行车动画


内容: 实现自行车模型在一个方向上的运动(轮子的滚动速度与自行车前进距离合适)


#include <glglut.h>
#include <math.h>
#include <iostream>
using namespace std;

//自行车中心点坐标
double x = 100, y = 330;
//车轮半径
double r = 30;
//自行车旋转角,及旋转角速度
GLint angle = 0;
GLint angleSpeed = 10;

void init()
{
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0.0, 600.0, 0.0, 600.0);
}

//画圆函数,传入中心点坐标(x,y),以及半径r
void drawCircle(double x, double y, double r)
{
	double N = 8;
	//把圆N等分,则每一等分为 360/N=2Pi/N
	double delta = 3.1415926*2.0 / N;
	//x0,y0,x1,y1分别代表该圆中第i和i+1个顶点的坐标,tmpx1,tmpy1,tmpx2,tmpy2则分别为对应顶点旋转后坐标.
	double x0, y0, x1, y1, tmpx1, tmpy1, tmpx2, tmpy2;

	glBegin(GL_LINE_LOOP);
	for (int i = 0; i <= N; i++)
	{
		//第i个顶点坐标
		x0 = x + r*cos(delta*i);
		y0 = y + r*sin(delta*i);
		//旋转计算
		tmpx1 = x + (x0 - x)*cos(angle % 360) - (y0 - y)*sin(angle % 360);
		tmpy1 = y + (x0 - x)*sin(angle % 360) + (y0 - y)*cos(angle % 360);
		//第i+1个顶点坐标
		x1 = x + r*cos(delta*(i + 1));
		y1 = y + r*sin(delta*(i + 1));
		//旋转计算
		tmpx2 = x + (x1 - x)*cos(angle % 360) - (y1 - y)*sin(angle % 360);
		tmpy2 = y + (x1 - x)*sin(angle % 360) + (y1 - y)*cos(angle % 360);

		glVertex2f(x, y);
		glVertex2f(tmpx1, tmpy1);
		glVertex2f(tmpx2, tmpy2);
	}
	glEnd();
}

//坐标变换
void DisplayFunc()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	//陆地横线
	glColor3f(0.0, 0.0, 0.0);
	glBegin(GL_LINES);
	glVertex2i(0, 300);
	glVertex2i(600, 300);
	glEnd();

	//自行车前后轮
	//x0,y0为后轮中心点的x,y坐标
	double x0, y0;
	x0 = x + 2 * 3.1415926*r*(double)angle / 360;
	drawCircle(x0, y, r);
	drawCircle(x0 + 90, y, r);

	//自行车横杠把手部分
	glColor3f(0.0, 0.0, 0.0);
	glBegin(GL_LINES);
	glVertex2i(x0, y);
	glVertex2i(x0 + 90, y);
	glVertex2i(x0 + 90, y);
	glVertex2i(x0 + 44, y + 120);
	glVertex2i(x0 + 66, y + 144);
	glVertex2i(x0 + 44, y + 120);
	glVertex2i(x0 + 22, y + 96);
	glVertex2i(x0 + 44, y + 120);
	glEnd();

	glFlush();
	glutSwapBuffers();
}

void MouseFunc(GLint button, GLint action, GLint x, GLint y)
{
	if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN)
	{
		angle += angleSpeed;
		glutPostRedisplay();
	}
	if (button == GLUT_RIGHT_BUTTON && action == GLUT_DOWN)
	{
		angle -= angleSpeed;
		glutPostRedisplay();
	}
}

void main(int argc, char ** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowPosition(400, 50);
	glutInitWindowSize(600, 600);
	glutCreateWindow("Computer Graphics:Bike");

	init();

	glutDisplayFunc(DisplayFunc);
	cout << "鼠标左键前进,右键后退" << endl;
	glutMouseFunc(MouseFunc);

	glutMainLoop();
}

最后效果:



最后

以上就是忧郁美女为你收集整理的OpenGL-学习之路-简单二维几何变换及应用的全部内容,希望文章能够帮你解决OpenGL-学习之路-简单二维几何变换及应用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部