实验一 VS+OpenGL绘图环境及基本图形绘制

 

一、实验目的

  1. 熟悉OpenGL的主要功能;
  2. 掌握OpenGL的绘图流程和原理;
  3. 掌握OpenGL核心函数的使用;
  4. 熟悉OpenGL基本图形元素的绘制函数。

二、实验内容

  1. 如预备知识所述,创建一个OpenGL工程,修改第一个程序中的Display()函数,如下:

 void Display(void)

{

    glClear (GL_COLOR_BUFFER_BIT); //清除缓存

    glBegin(GL_LINES);             //开始画线

    glColor3f (1.0f, 1.0f, 0.0f);          //设置颜色为黄色

//设置第一根线的两个端点,请注意:OpenGL坐标系的原点是在屏幕左下角

    glVertex2f(10.0f, 50.0f);

    glVertex2f(110.0f, 50.0f);

    glColor3f (1.0f, 0.0f, 0.0f);           //设置颜色为红色

//设置第二根线的两个端点

    glVertex2f(110.0f, 50.0f);

    glVertex2f(110.0f, 150.0f);

    glEnd();      //画线结束

    glFlush ();  

}

该程序是在窗口中画两条线,分别用黄色和红色绘制。如上所述,OpenGL是一个状态机,glBegin(UINT State)可以设定如下状态:

GL_POINTS   画点

GL_LINES    画线,每两个顶点(Vertex)为一组

GL_LINE_STRIP  画线,把若干个顶点顺次连成折线

GL_LINE_LOOP   画线,把若干个顶点顺次连成封闭折线

GL_TRIANGLES   画三角形,每三个顶点为一组

GL_QUADS    画四边形,每四个顶点为一组

GL_POLYGON     画多边形

还有GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUAD_STRIP 等等。另外,程序可以有多组glBegin()、glEnd()并列的形式,如:

... ...

glBegin(GL_LINES);

......

glEnd();

 

glBegin(GL_QUADS);

... ...

glEnd();

... ...

要求:利用OpenGL库函数绘制基本图形,输出绘制结果。

  1. 绘制函数,通过设置观察矩形和视口,使得曲线在窗口的显示效果如下图所示。

 

 

  1. 利用OpenGL函数绘制圆弧和心脏线

圆弧通过其中心c,外接圆的半径R,以及开始的角度a和它展开的角度b来表示,函数可以表示为:

 

void drawArc(Point2 center, float radius, float startAngle, float sweep)

心脏线要求平铺屏幕窗口,并创建菜单,通过菜单设定心脏线的大小(K值决定大小),通过鼠标动作改变心脏线的颜色。心脏线的极坐标形式为:

参考代码:

恐龙平铺屏幕窗口polyline.cpp

菜单GlutMenu.cpp

三、实验设计思路

1. 创建一个OpenGL工程,修改初始化代码Display函数,glBegin(GL_LINES)开始画线;glColor3f ()设置颜色;glVertex2f()设置第一根线的两个端点。从而得到两条颜色及位置不同的线段。

2.修改Display函数,glBegin(GL_LINE_STRIP);开始画线,把若干个顶点顺次连成折线glColor3f(0.0f, 0.0f, 0.0f);设置颜色,利用for循环描点glVertex2f(i, exp(-i) * cos(2 * 3.14 * i));函数。再修改Initial函数中gluOrtho2D(0.0, 4.0, -1.0, 1.0);的X与Y轴显示区域。

3. 圆弧通过其中心c,外接圆的半径R,以及开始的角度a和它展开的角度b来表示;对心脏线进行绘制,创建菜单以控制心脏线的大小,用鼠标左键控制菜单弹出,K设置了五个心脏线大小。通过鼠标右键来控制颜色,glColor3f(red/256.0+0.5, green/256.0+0.5, blue/256.0+0.5);设置随机数,最后通过glViewport调节视口,来实现了一个5*5的平铺屏幕窗口效果。

四、实验代码

1.  

#include <gl/glut.h>

void Initial(void)
{
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);      //设置窗口背景颜色为白色
	glMatrixMode(GL_PROJECTION);     //设置投影参数
	glLoadIdentity();
	gluOrtho2D(0.0, 200.0, 0.0, 200.0);
}

void Display(void)
{
	glClear(GL_COLOR_BUFFER_BIT); //清除缓存
	glBegin(GL_LINES);				//开始画线
	glColor3f(1.0f, 1.0f, 0.0f);	        //设置颜色为黄色
//设置第一根线的两个端点,请注意:OpenGL坐标系的原点是在屏幕左下角
	glVertex2f(10.0f, 50.0f);
	glVertex2f(110.0f, 50.0f);
	glColor3f(1.0f, 0.0f, 0.0f);	         //设置颜色为红色
//设置第二根线的两个端点
	glVertex2f(110.0f, 50.0f);
	glVertex2f(110.0f, 150.0f);
	glEnd();		//画线结束
	glFlush();
}


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

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);  //初始化窗口的显示模式
	glutInitWindowSize(400, 400);                  //设置窗口的尺寸
	glutInitWindowPosition(100, 120);               //设置窗口的位置
	glutCreateWindow("矩形");                    //创建一个名为矩形的窗口
	glutDisplayFunc(Display);                     //设置当前窗口的显示回调函数
	Initial();                                    //完成窗口初始化
	glutMainLoop();                             //启动主GLUT事件处理循环
												//		return 0;
}

 2.

 

#include <gl/glut.h>
#include<math.h> 

void Initial(void)
{
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);      //设置窗口背景颜色为白色
	glMatrixMode(GL_PROJECTION);     //设置投影参数
	glLoadIdentity();
	gluOrtho2D(0.0, 4.0, -1.0, 1.0);
}

void Display(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glBegin(GL_LINE_STRIP);
	glColor3f(0.0f, 0.0f, 0.0f);
	for (float i = 0; i <= 4; i = i + 0.01)
	{
		glVertex2f(i, exp(-i) * cos(2 * 3.14 * i));
	}

	glEnd();

	glFlush();
}


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

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);  //初始化窗口的显示模式
	glutInitWindowSize(400, 400);                  //设置窗口的尺寸
	glutInitWindowPosition(100, 120);               //设置窗口的位置
	glutCreateWindow("矩形");                    //创建一个名为矩形的窗口
	glutDisplayFunc(Display);                     //设置当前窗口的显示回调函数
	Initial();                                    //完成窗口初始化
	glutMainLoop();                             //启动主GLUT事件处理循环
												//		return 0;
}

3.1

#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>

GLuint startList;

void init(void)
{
    GLUquadricObj* qobj;

    startList = glGenLists(1);
    qobj = gluNewQuadric();
    gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); /* 只画边缘  */
    gluQuadricNormals(qobj, GLU_NONE);/*不算NORMAL(顶点的方向)*/
    glNewList(startList, GL_COMPILE);/*只编译DISPLAY LIST不绘制*/
    gluPartialDisk(qobj, 0.0, 1.0, 20, 4, 0.0, 225.0);/* 第一个参数是A quadric object,然后内圆半径为0.0,外圆半径为1.0,z轴向分割片数,最后两个参数是圆弧的起始角和结束角  */
    glEndList();
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPushMatrix();

    glColor3f(1.0, 1.0, 0.0);
    glCallList(startList);

    glPopMatrix();
    glFlush();
}

void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (w <= h)
        glOrtho(-2.5, 2.5, -2.5 * (GLfloat)h / (GLfloat)w,
            2.5 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);
    else
        glOrtho(-2.5 * (GLfloat)w / (GLfloat)h,
            2.5 * (GLfloat)w / (GLfloat)h, -2.5, 2.5, -10.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

/* ARGSUSED1 */
void keyboard(unsigned char key, int x, int y)
{
    switch (key) {
    case 27:
        exit(0);
        break;
    }
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(300, 300);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(argv[0]);
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutMainLoop();
    return 0;
}

 

3.2 

#include <windows.h>
#include<iostream>
#include <GL/glut.h>
#include <cmath>

#define PI 3.1415926
#define RED 1
#define GREEN 2
#define BLUE 3
#define WHITE 4
//初始化OpenGL场景

float red = 1.0, blue = 1.0, green = 1.0;
float K = 1;
void myinit(void)
{
	glClearColor(0.0, 0.0, 0.0, 0.0);		//将背景置成黑色
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(-12.0, 12.0, -12.0, 12.0);
}
//用户的绘图过程

void mydisplay()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//glColor3f(1.0, 0.0, 0.0);
	glColor3f(red / 256.0 + 0.5, green / 256.0 + 0.5, blue / 256.0 + 0.5);
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++)
		{
			glViewport(i * 64, j * 64, 100, 100);
			glBegin(GL_LINE_LOOP);
			for (float x = 0; x < 2 * 3.14; x = x + 0.1)
			{
				glVertex2f((1 + cos(x)) * cos(x) * K, (1 + cos(x)) * sin(x) * K);
			}
			glEnd();
		}
	}
	glFlush();
}

void myMouse(int button, int state, int x, int y) {

	if (state == GLUT_DOWN)
	{
		if (button == GLUT_RIGHT_BUTTON)
		{
			red = rand() / 128;
			blue = rand() / 128;
			green = rand() / 128;

		}
		else if (button == GLUT_RIGHT_BUTTON)
		{
			glClearColor(1.0f, 0.0f, 0.0f, 0.0f); // Red
			glClear(GL_COLOR_BUFFER_BIT);
			glFlush();
		}
	}

}
void processMenuEvents_two(int option) {
	switch (option)
	{
	case 1:K = 1; break;
	case 2:K = 2; break;
	case 3:K = 3; break;
	case 4:K = 4; break;
	case 5:K = 5; break;
	default:
		break;
	}
}

int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(0, 0);
	glutInitWindowSize(400, 400);
	glutCreateWindow("心脏线");
	myinit();

	glutDisplayFunc(mydisplay);
	glutIdleFunc(mydisplay);//空闲回调函数
	glutMouseFunc(myMouse);

	glutCreateMenu(processMenuEvents_two);
	glutAddMenuEntry("one", 1);
	glutAddMenuEntry("two", 2);
	glutAddMenuEntry("three", 3);
	glutAddMenuEntry("four", 4);
	glutAddMenuEntry("five", 5);
	glutAttachMenu(GLUT_LEFT_BUTTON);
	glutMainLoop();
}

 

 五、实验结果及心得体会

1.

 2.

3

此次实验,学会了基本的VS+OpenGL绘图环境及基本图形绘制,了解了OpenGL的主要功能以及绘图流程和原理。实现了OpenGL核心函数的使用以及基本图形元素的绘制函数。还实现了鼠标交互等功能。通过本次实验绘制了不同的函数图像,对今后的学习也有了较大的帮助。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐