計算機圖形學-實驗3-掌握利用OpenGL函數進行鼠標、鍵盤操作,創建菜單

實驗三:2學時)

 

一、 實驗目的:

掌握利用OpenGL函數進行鼠標、鍵盤操作,創建菜單等

 

二、 實驗內容:

1、用鼠標拖動畫直線,線段終點始終跟隨鼠標移動;畫線可以利用實驗1或實驗2中已經實現的畫線功能;

2、使用菜單界面修改直線的顏色;

3、利用鍵盤控制直線在屏幕上移動;

 

三、 實現效果及步驟(或流程)

1、用鼠標拖動畫直線,線段終點始終跟隨鼠標移動;

(1)畫線採用實驗二的方法。

(2)編寫鼠標響應事件,實現按下標記第一個點,擡起獲得第二個點並畫線。代碼如圖:


(3)獲取鼠標實時移動座標,實現隨鼠標位置移動的畫線效果。代碼如圖:

 

(4)實現效果如下圖:



2、使用菜單界面修改直線的顏色。

(1)在主函數裏添加菜單的回調函數,再添加若干菜單項,參數value用以標記菜單項。實現代碼如圖:

 

(2)實現效果如圖:

 


3、利用鍵盤控制直線在屏幕上移動;

(1)主函數中添加鍵盤響應的回調函數:

glutSpecialFunc(ProcessSpecialKeyboead);

(2)編寫回調函數代碼,根據鍵盤輸入,修改線的座標並重新繪製直線。代碼如圖:

 

(3)實現效果如圖:

 

向上移動後;

 

四、 創新設計和實現方法

1、創建菜單的子菜單;

(1)利用glutAddSubMenu函數將其他菜單加入到該項下作爲子菜單。

(2)編寫邏輯函數,參數value接收輸入。

 

(3)實現效果如下圖:



源碼如下:

// test3.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include <math.h>
#include <GL/glut.h>

#define GLUT_LEFT_BUTTON    0
#define GLUT_MIDDLE_BUTTON  1
#define GLUT_RIGHT_BUTTON    2
#define GLUT_DOWN        0
#define GLUT_UP          1
int Width = 500, Height = 500;
int x01, y01, x02, y02;
int FirstPointHaveDraw = 0;
int RightButtonDown = 0;
float red = 0.0f, green = 0.0f, blue = 0.0f;
int moveSpeed = 2;
void init(void)
{
	glClearColor(1.0, 1.0, 1.0, 0.0);  // Set display-window color to white.
	glMatrixMode(GL_PROJECTION);       // Set projection parameters.
	gluOrtho2D(0.0, Width, 0.0, Height);  //設置窗口座標範圍
}

void lineBres(int x0, int y0, int xEnd, int yEnd, int red, int green, int blue)
{
	glPointSize(4);
	glColor3f(red, green, blue);
	glBegin(GL_POINTS);
	//畫第一個點
	if (x0 > xEnd)
	{
		int t;
		t = x0; x0 = xEnd; xEnd = t;
		t = y0; y0 = yEnd; yEnd = t;
	}
	int x = x0;
	int y = y0;
	glVertex2i(x, y);
	//當線段垂直時。
	if (x0 == xEnd)
	{
		while (y < yEnd)
		{
			y++;
			glVertex2i(x, y);
		}
		glEnd();
		glFlush();
		return;
	}
	//當線段水平時。
	if (y0 == yEnd)
	{
		while (x < xEnd)
		{
			x++;
			glVertex2i(x, y);
		}
		glEnd();
		glFlush();
		return;
	}
	int dx = xEnd - x0;
	int dy = yEnd - y0;
	int twoDx = 2 * dx;
	int twoDy = 2 * dy;
	int twoDyMinusDx = 2 * (dy - dx);
	int twoDxMinusDy = 2 * (dx - dy);
	int twoDxAddDy = 2 * (dx + dy);
	int p;
	double k = (double)(yEnd - y0) / (double)(xEnd - x0);
	//斜率
	//當線段斜率0<k<=1時。
	if (0 < k && k <= 1)
	{
		p = 2 * dy - dx;
		while (x < xEnd)
		{
			x++;
			if (p < 0)
			{
				p += twoDy;
			}
			else
			{
				y++;
				p += twoDyMinusDx;
			}
			glVertex2i(x, y);
		}
		glEnd();
		glFlush();
		return;
	}
	//當線段斜率-1<=k<0時。
	if (k < 0 && k >= -1)
	{
		p = 2 * dy + dx;
		while (x < xEnd)
		{
			x++;
			if (p >= 0)
				p += twoDy;
			else
			{
				y--;
				p += twoDxAddDy;
			}
			glVertex2i(x, y);
		}
		glEnd();
		glFlush();
		return;
	}
	//當線段斜率k<-1時。
	if (k < -1)
	{
		p = 2 * dx - dy;
		while (y > yEnd)
		{
			y--;
			if (p >= 0)
				p -= twoDx;
			else
			{
				x++;
				p -= twoDxAddDy;
			}
			glVertex2i(x, y);
		}
		glEnd();
		glFlush();
		return;
	}
	//當線段斜率k>1時。
	if (k > 1)
	{
		p = dy;
		while (y < yEnd)
		{
			y++;
			if (p < 0)
			{
				p += twoDx;
			}
			else
			{
				x++;
				p -= twoDyMinusDx;
			}
			glVertex2i(x, y);
		}
		glEnd();
		glFlush();
		return;
	}
}

void Drawline(int button, int state, int x, int y)
{
	glPointSize(1);
	glColor3f(0.1, 0.0, 0.0);
	if (RightButtonDown == 0)
	{
		if (button == GLUT_LEFT_BUTTON)
		{
			if (state == GLUT_DOWN)
			{
				if (FirstPointHaveDraw == 0)
				{
					x01 = x;
					y01 = Height - y;
					glPointSize(2);
					glBegin(GL_POINTS);
					glVertex2i(x01, y01);
					glEnd();
					glFlush();
					FirstPointHaveDraw = 1;
				}
				printf("畫下點 x:%d,y:%d\n", x01, y01);
			}
			else
			{
				x02 = x;
				y02 = Height - y;
				lineBres(x01, y01, x02, y02, red, green, blue);
				FirstPointHaveDraw = 0;
			}
		}
	}
}

void mousemove(int x, int y)
{
	glClear(GL_COLOR_BUFFER_BIT);
	printf("鼠標移動中, x:%d,y:%d\n", x, Height - y);
	lineBres(x01, y01, x, Height - y, red, green, blue);
}

void ColorMenu(int value) {

	switch (value)
	{
	case 1:red = 1.0; green = 0.0; blue = 0.0; break;
	case 2:red = 0.0; green = 1.0; blue = 0.0; break;
	case 3:red = 0.0; green = 0.0; blue = 1.0; break;
	default:break;
	}
}

void myMenu(int value)
{
	if (value == 0)
	{
		exit(0);
	}
	else
	{
		ColorMenu(value);
	}
}

void ProcessSpecialKeyboead(int key, int x, int y)
{
	if (GLUT_KEY_UP == key)
	{
		printf("up\n");
		y01 += moveSpeed;
		y02 += moveSpeed;
		glClear(GL_COLOR_BUFFER_BIT);
		lineBres(x01, y01, x02, y02, red, green, blue);
		glFlush();
	}
	if (GLUT_KEY_DOWN == key)
	{
		printf("down\n");
		y01 -= moveSpeed;
		y02 -= moveSpeed;
		glClear(GL_COLOR_BUFFER_BIT);
		lineBres(x01, y01, x02, y02, red, green, blue);
		glFlush();
	}
	if (GLUT_KEY_LEFT == key)
	{
		printf("left\n");
		x01 -= moveSpeed;
		x02 -= moveSpeed;
		glClear(GL_COLOR_BUFFER_BIT);
		lineBres(x01, y01, x02, y02, red, green, blue);
		glFlush();
	}
	if (GLUT_KEY_RIGHT == key)
	{
		printf("right\n");
		x01 += moveSpeed;
		x02 += moveSpeed;
		glClear(GL_COLOR_BUFFER_BIT);
		lineBres(x01, y01, x02, y02, red, green, blue);
		glFlush();
	}
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);                         // Initialize GLUT.
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);   // Set display mode.
	glutInitWindowPosition(100, 100);   // Set top-left display-window position.
	glutInitWindowSize(Width, Height);      // 設置窗口在顯示器上的大小
	glutCreateWindow("An Example OpenGL Program"); // Create display window.

	init();                            // Execute initialization procedure.
	glClear(GL_COLOR_BUFFER_BIT);
	glutMouseFunc(Drawline);
	glutMotionFunc(mousemove);
	int sub_menu;
	sub_menu = glutCreateMenu(ColorMenu);
	glutAddMenuEntry("Red", 1);//添加菜單項  
	glutAddMenuEntry("Green", 2);
	glutAddMenuEntry("Blue", 3);
	glutCreateMenu(myMenu);//註冊菜單回調函數
	//glutAddMenuEntry("Rotate", 4);
	glutAddSubMenu("Color", sub_menu);
	glutAddMenuEntry("Exit", 0);
	glutAttachMenu(GLUT_RIGHT_BUTTON);//把當前菜單註冊到指定的鼠標鍵  
	glutSpecialFunc(ProcessSpecialKeyboead);
	glutMainLoop();                    // Display everything and wait.
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章