图形学实验二 直线生成算法

实验二 直线生成算法

实验类型:设计型   实验学时:2实验要求:必修

一、实验目的

理解基本图形元素光栅化的基本原理,掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法。

二、实验内容

1.根据所给的直线光栅化的示范源程序,在计算机上编译运行,输出正确结果;

2.指出示范程序采用的算法,以此为基础将其改造为中点线算法或Bresenham算法,写入实验报告;

3.根据示范代码,将其改造为圆的光栅化算法,写入实验报告;

4.了解和使用OpenGL的生成直线的命令,来验证程序运行结果。

三、实验原理

下面介绍下OpenGL画线的一些基础知识和glutReshapeFunc()函数。

(1)数学上的直线没有宽度,但OpenGL的直线则是有宽度的。同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的。可以认为,OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定。这里的线由一系列顶点顺次连结而成,有闭合和不闭合两种。

前面的实验已经知道如何绘“点”,那么OpenGL是如何知道拿这些顶点来做什么呢?是一个一个的画出来,还是连成线?或者构成一个多边形?或是做其它事情呢?为了解决这一问题,OpenGL要求:指定顶点的命令必须包含在glBegin函数之后,glEnd函数之前(否则指定的顶点将被忽略),并由glBegin来指明如何使用这些点。

则这两个点将分别被画出来。如果将GL_POINTS替换成GL_LINES,则两个点将被认为是直线的两个端点,OpenGL将会画出一条直线。还可以指定更多的顶点,然后画出更复杂的图形。另一方面,glBegin支持的方式除了GL_POINTS和GL_LINES,还有GL_LINE_STRIP,GL_LINE_LOOP,GL_TRIANGLES,GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN等,每种方式的大致效果如图2所示:

图2   OpenGL几何图元类型

基础:

升级1:

升级三:

紫色的要求写出通用算法:

四、实验示范代码(略)

五、实验步骤

1 在Windows xp/win7操作环境下,启动VC;

2 建立W32 Console Application 的应用工程;

3 建立源程序编辑环境,进行编辑源程序。

4 调试运行程序,完成实验。

六、实验结果处理

演示结果并保存相关文件。

七、实验注意事项

注意编程环境的配置,即在Windows环境下,OpenGL扩展库相关文件的配置,把头文件“GL.H”、库文件“OPENGL32.LIB”和动态链接库“OPENGL32.DLL”配置到相应的目录下。

八、预习与思考题

预习:阅读课本相关内容,仔细阅读示范代码。

思考题:如何实现图线颜色和线宽的交互选择。

九、实验报告要求

1、实验报告中应包括相关操作步骤和程序代码和运行效果截图。

2.书写实验报告时要结构合理,层次分明,在分析描述的时候,需要注意语言的流畅。

基础代码:


#include "pch.h"
#include <iostream>
#include<GL/glut.h>

void LineDDA(float x0, float y0, float x1, float y1)
{
	float x, dy, dx, y;
	float m;
	dx = x1 - x0;
	dy = y1 - y0;
	m = dy / dx;// 计算直线斜率
	y = y0;

	glColor3f(1.0f, 1.0f, 0.0f);
	glPointSize(1);
	for (x = x0; x <= x1; x++)
	{
		glBegin(GL_POINTS);
		glVertex2i(x, (float)(y + 0.5));
		glEnd();
		y += m;
	}

}


void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0f, 0.0f, 0.0f);
	glRectf(25., 25.0, 75.0, 75.0);

	glPointSize(5);
	glBegin(GL_POINTS);//绘制左下方的青色点
	glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(0.0f, 0.0f);
	glEnd();

	LineDDA(0,0, 200, 200);//传参画黄色线条

	glBegin(GL_LINES);//画绿色线
	glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(100.0f, 0.0f);
	glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(180.0f, 240.0f);
	glEnd();

	glFlush();
}

void Init()
{
	glClearColor(0.0, 0.0, 0.0, 0.0 );
	glShadeModel(GL_FLAT);//默认背景色
}

void Reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
}

int main(int argc,char *argv[])

{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);
	glutCreateWindow("Hello world!");
	Init();
	glutDisplayFunc(myDisplay);
	glutReshapeFunc(Reshape);
	glutMainLoop();
	return 0;

}

升级1:


#include "pch.h"
#include <iostream>
using namespace std;
#include<GL/glut.h>
int color1=0, color2=0, color3=0;
int numbercolor;//定义线段颜色
int LineSize;//定义线段宽度;
void changecolor(int numbercolor)
{
	if (numbercolor == 1) color1 = 1;
	else if (numbercolor == 2) color2 = 1;
	else if (numbercolor == 3) color3 = 1;
	else if (numbercolor == 4) { color1 = 1; color2 = 1; }
	else if (numbercolor == 5) { color2 = 1; color3 = 1; }
	else if (numbercolor == 6) { color1 = 1; color3 = 1; }
	else if (numbercolor == 7) { color1 = 1; color2 = 1; color3= 1; }
	else cout << "数据不合法!";
}
void LineDDA(float x0, float y0, float x1, float y1)
{
	float x, dy, dx, y;
	float m;//定义变量表示斜率
	dx = x1 - x0;
	dy = y1 - y0;
	m = dy / dx;
	y = y0;

	
	glColor3f(color1, color2, color3);
	glPointSize(LineSize);
	for (x = x0; x <= x1; x++)
	{
		glBegin(GL_POINTS);
		glVertex2i(x, (float)(x + 0.5));
		glEnd();
		y += m;
	}
}

void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0, 1.0, 1.0);//画左起第一个大矩形
	glRectf(25.0, 25.0, 75.0, 75.0);
	glRectf(120.0, 200.0, 125, 205.0);//画第二个小矩形


	glPointSize(5);
	glBegin(GL_POINTS);
	glColor3f(color1, color2, color3); glVertex2f(0.0, 0.0);
	glEnd();

	LineDDA(0.0, 0.0, 200, 200);//画左起第一条线

	glBegin(GL_LINES);//左起画第二条线
	glColor3f(1.0, 0.0, 0.0); glVertex2f(100, 0);
	glColor3f(0.0, 1.0, 0.0); glVertex2f(180.0, 240.0);
	glEnd();

	glFlush();
}


void Init()
{
	glClearColor(0.0, 0.0,0.0, 0.0);
	glShadeModel(GL_FLAT);
}


void ReShape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
}
int main(int argc,char *argv[])
{
	
	cout << "画线颜色按以下约定:"<<endl;
	cout << "  红    绿      兰      黄      青      玫瑰    白"<<endl;
	cout << "1(100); 2(010); 3(001); 4(110); 5(011); 6(101); 7(111)"<<endl;
	cout << "请输入画线颜色(1-7) :";
	cin >> numbercolor;
	cout << "请输入线段宽度(1-10):";
	cin >> LineSize;
	changecolor(numbercolor);
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);
	glutCreateWindow("Hello world!");
	Init();
	glutDisplayFunc(myDisplay);
	glutReshapeFunc(ReShape);
	glutMainLoop();
	return 0;
}



// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门提示: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

升级2:


#include "pch.h"
#include<math.h>
#include<GL/glut.h>
#include <iostream>
using namespace std;
float PI = 3.1415926f;
int instruction,n;
void plantCircle(float R,float color1,float color2,float color3){
	int i = 0,n = 1000;//控制n的大小来相对精确画圆
	glColor3f(color1, color2, color3);//设置圆形的颜色
	glBegin(GL_POLYGON);
	for (i = 0; i < n; i++)
		glVertex2f(R*cos(2 * PI*i / n), R*sin(2 * PI*i / n));//通过数学计算定义顶点
	glEnd();
}
void plantLine(float pi,float pi_Add,float R,float r)//绘制菱形边线、边心连线
{	
		for (pi; pi <= 2 * PI; pi += pi_Add ){ //调试过程中,发现PI/6如果表达成:(1/6)*PI会产生不必要的麻烦
			glColor3f(0.0, 0.0, 0.0);
			glBegin(GL_LINE_STRIP);
			if (n == 1) { glVertex2f(0, R); glVertex2f(0, -R); }
			else {
				glVertex2f(0.0, 0.0);
				glVertex2f(r*sin(pi - pi_Add), r*cos(pi - pi_Add));//float r = 0.3;
				glVertex2f(R*sin(pi - pi_Add / 2), R*cos(pi - pi_Add / 2));//float R= 0.52;
				glVertex2f(0.0, 0.0);
				glVertex2f(r*sin(pi), r*cos(pi));
				glVertex2f(R*sin(pi - pi_Add / 2), R*cos(pi - pi_Add / 2));//float R= 0.52;
				}
			glEnd();
		}	
}
void plantLingxing(float pi, float pi_add, float R, float r)/*绘制菱形的函数*/{
	for (pi; pi <= 2 * PI; pi += pi_add){ 
		glBegin(GL_POLYGON);
		glVertex2f(0.0, 0.0);
		glVertex2f(r*sin(pi - pi_add), r*cos(pi - pi_add));//float r = 0.3;
		glVertex2f(R*sin(pi - pi_add / 2), R*cos(pi - pi_add / 2));//float R= 0.52;
		glVertex2f(r*sin(pi), r*cos(pi));
		glEnd();
	}	
}
void myDisplay(void){
	glClear(GL_COLOR_BUFFER_BIT);
	if (instruction == 1){
		plantCircle(0.52, 14 / 255.0, 0.0, 140 / 255.0);//绘制蓝色大背景的圆形
		glColor3f(1.0, 1.0, 1.0);//定义12角星的颜色
		plantLingxing(PI / 12, PI / 6,0.52,0.3);
		plantCircle(0.28, 14 / 255.0, 0.0, 140 / 255.0);//绘制12角星内部的大蓝色圆
		plantCircle(0.26, 1.0, 1.0, 1.0);//绘制12角星内部的小圆	
	}
	else
	{/*团中央的徽*/
		if (n == 5){
			plantCircle(0.52, 1.0, 1.0, 0.0);
			plantCircle(0.48, 1.0, 0.0, 0.0);
			glColor3f(1.0, 1.0, 0.0);
			plantLingxing(PI / n, 2 * PI / n, 0.48, 0.2);
			plantLine(PI / n, 2 * PI / n, 0.48, 0.2);
		}
		else{/*普通图形*/
			plantCircle(0.52, 1.0, 0.0, 1.0);//绘制粉色大圆
			glColor3f(1.0, 1.0, 1.0);
			plantLingxing(PI / n, 2 * PI / n, 0.52, 0.24);
			plantLine(PI / n, 2 * PI / n, 0.52, 0.24);//glBegin() 与 glEnd()之间只能加一个操作函数,否则出错(无法显示)
			}
	}
	glFlush();
}
void Init(){
	glClearColor(0.0, 0.0, 0.0, 0.0);//方框背景置白
	glShadeModel(GL_FLAT);
}
int main(int argc, char *argv[]){
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	cout << "说明:图案形式选择1:绘制国民党党徽;"<<endl;
	cout << "图案形式选择不为1,顶点数输入5:绘制共青团团徽!" << endl;
	cout << "其余绘制花型图案!" << endl;
	cout<<"请图案形式(1:国民党党徽, 其余不为1):" << endl;
	cin >> instruction;
	if (instruction != 1){	
		cout << "请输入多边形的顶点数(1<n<100):" << endl;
		cin >> n;
	}
	glutInitWindowSize(600, 600);
	glutCreateWindow("Hello world!");
	Init();
	glutDisplayFunc(myDisplay);
	glutMainLoop();
	return 0;
}


结果即为实验要求!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北溟南风起

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值