OpenGL實驗二 利用滑鼠、鍵盤,選單等方式對圖元進行互動操作
- 實驗目的:
利用滑鼠、鍵盤,選單等方式對圖元進行互動操作
- 實驗內容:
1、用滑鼠拖動畫直線,線段終點始終跟隨滑鼠移動;
2、使用選單介面修改直線的顏色;
3、利用鍵盤控制直線在螢幕上移動;
可以改進的設想:
1.做一個畫圖程式 可以在滑鼠移動函式裡修改,每次畫點,並定義全域性陣列儲存點的座標;
2.修改顏色時可以彈出一個顏色表,可以用子視窗實現,並且定義模式為拾取模式
3.可以畫多根線,然後按下右鍵,拖動滑鼠畫一個矩形,在矩形區域內的線段會變色
4.點選某個線,然後拖動線段
5.Ctrl + 滾輪 放大縮小線段
5. 同時按下上方向鍵和左方向鍵,然後線段想左上方移動(沒思路)
原始碼:
/*
IDE:codeblocks
1、用滑鼠拖動畫直線,線段終點始終跟隨滑鼠移動;
2、使用選單介面修改直線的顏色;
3、利用鍵盤控制直線在螢幕上移動;
*/
#include <windows.h>
#include <GL/glut.h>
#include <iostream>
#include <stdio.h>
using namespace std;
double WINHEIGHT = 0,WINWIDTH = 0;
bool FirstPointHadDraw = false, LineHadDraw = false;
int x0 = 0, y0 = 0, xEnd = 0, yEnd = 0;
double moveSpeed = 3;
void init();
void MyIdle();
void MyReshape(int w, int h);
void display(void);
void drawLine(int x0, int y0,int xEnd,int yEnd);
void setpixel(int x, int y);
void MyMouse(int button, int state, int x, int y);
void MyMouseMotion(int x,int y);
void MyKeyboard(unsigned char key, int x, int y);
void MySpecialKey(int key, int x, int y);
void MyCreateMenu();
void MajorMenu(int value);
void colorMenu(int value);
void linewidthMenu(int value);
void moveSpeedMenu(int value);
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(500,300);
glutCreateWindow("實驗2 利用滑鼠、鍵盤,選單等方式對圖元進行互動操作");
init();
MyCreateMenu();
glutReshapeFunc (MyReshape);
//glutIdleFunc(MyIdle);
glutDisplayFunc(display);
glutMouseFunc (MyMouse);
glutMotionFunc(MyMouseMotion);
glutKeyboardFunc (MyKeyboard);
glutSpecialFunc(MySpecialKey);
glutMainLoop();
}
void display(void)
{
cout<<"Displaying... ";
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
cout<<"Displayed! "<<endl;
}
void MyCreateMenu()
{
int majorMenuID = glutCreateMenu(MajorMenu);
int colorMenuID = glutCreateMenu(colorMenu);
int linewidthMenuID = glutCreateMenu(linewidthMenu);
int moveSpeedMenuID = glutCreateMenu(moveSpeedMenu);
glutSetMenu(majorMenuID);//設定當前選單
glutAttachMenu(GLUT_RIGHT_BUTTON);//繫結到滑鼠右鍵
glutAddSubMenu("顏色變化",colorMenuID);
glutAddSubMenu("粗細變化",linewidthMenuID);
glutAddSubMenu("移動速度變化",moveSpeedMenuID);
glutAddMenuEntry("清屏", 3);
glutAddMenuEntry("退出", 4);
glutSetMenu(colorMenuID);
glutAddMenuEntry("紅色", 1);
glutAddMenuEntry("綠色", 2);
glutAddMenuEntry("藍色", 3);
glutSetMenu(linewidthMenuID);
glutAddMenuEntry("設為1", 1);
glutAddMenuEntry("設為3", 2);
glutAddMenuEntry("設為5", 3);
glutSetMenu(moveSpeedMenuID);
glutAddMenuEntry("設為1", 1);
glutAddMenuEntry("設為3(預設)", 2);
glutAddMenuEntry("設為5", 3);
return;
}
void MajorMenu(int value)
{
switch(value)
{
case 3:
{
glClear(GL_COLOR_BUFFER_BIT);
glFlush();
break;
}
case 4:
exit(0);
}
return;
}
void colorMenu(int value)
{
cout<<"顏色設定中.........."<<endl;
switch(value)
{
case 1:
glColor3f(1.0, 0.0, 0.0);
break;
case 2:
glColor3f(0.0, 1.0, 0.0);
break;
case 3:
glColor3f(0.0, 0.0, 1.0);
break;
}
drawLine(x0,y0,xEnd,yEnd);
return;
}
void linewidthMenu(int value)
{
cout<< "線寬設定中.........."<<endl;
switch(value)
{
case 1:
glLineWidth(1);
break;
case 2:
glLineWidth(3);
break;
case 3:
glLineWidth(5);
break;
}
drawLine(x0,y0,xEnd,yEnd);
return;
}
void moveSpeedMenu(int value)
{
cout<< "移動速度設定中.........."<<endl;
switch(value)
{
case 1:
moveSpeed = 1;
break;
case 2:
moveSpeed = 3;
break;
case 3:
moveSpeed = 5;
break;
}
return;
}
void MyMouse(int button, int state, int x, int y)
{
if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
cout<<"左鍵被按下 ";
x0 = x;
y0 = WINHEIGHT - y;
setpixel(x0,y0);
FirstPointHadDraw = true;
}
if(button == GLUT_LEFT_BUTTON &&state == GLUT_UP)
{
cout<<"左鍵被釋放 "<<endl;
LineHadDraw = true;
}
}
//移動事件 鍵被按下的同時發生移動
void MyMouseMotion(int x,int y)
{
cout<<"滑鼠移動中... ";
if(true ==FirstPointHadDraw)
{
xEnd = x;
yEnd = WINHEIGHT - y;
drawLine(x0,y0,xEnd,yEnd);
}
return;
}
void drawLine(int x, int y,int x2,int y2)
{
cout<<"準備畫線:"<< x0<<" "<< y0<<" " << xEnd<<" "<< yEnd<<" "<<endl;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2f(x,y);
glVertex2f(x2,y2);
glEnd();
cout<<"畫線完成 ";
glFlush();
return;
}
void MyKeyboard(unsigned char key, int x, int y)
{
//27為ESC鍵
if(key==27)
{
exit(0);
}
}
void MySpecialKey(int key, int x, int y)
{
glutGetModifiers();
switch(key)
{
case GLUT_KEY_UP:
{
y0 += moveSpeed;
yEnd += moveSpeed;
break;
}
case GLUT_KEY_DOWN:
{
y0 -= moveSpeed;
yEnd -= moveSpeed;
break;
}
case GLUT_KEY_LEFT:
{
x0 -= moveSpeed;
xEnd -= moveSpeed;
break;
}
case GLUT_KEY_RIGHT:
{
x0 += moveSpeed;
xEnd += moveSpeed;
break;
}
}
drawLine(x0,y0,xEnd,yEnd);
return;
}
//返回調整大小後的視窗大小 w,h
void MyReshape(GLsizei w, GLsizei h)
{
//view port 左下角為0,0
//視窗在高度方向變長,截圖也要在該方向上拉長相同比例
//寬度方向拉長,截圖也要在該方向上拉長相同比例
cout<<"Reshaping... "<<w<<" "<<h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<=h)
gluOrtho2D(0,500, 0,500 * h/w);
else
gluOrtho2D(0,500 * w/h, 0,500);
glViewport(0,0,w,h);
WINWIDTH = w;
WINHEIGHT = h;
cout<<"Reshaped"<<endl;
}
void setpixel(int x, int y)
{
glBegin(GL_POINTS);
glVertex2i(x,y);
glEnd();
return;
}
void MyIdle()
{
glutPostRedisplay();
}
void init()
{
//反射任何光,為白色
//gluOrtho2D(left, right, bottom, top);
//glortho(x_min x_max y_min y_max near top)
cout<<"Initing... ";
glClearColor (1.0, 1.0, 1.0, 1.0);
glColor3f(0.0, 0.0, 0.0);
glPointSize(2.0);
glLineWidth(2.0);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho(0.0f, WINWIDTH, 0.0f, WINHEIGHT, 1.0, -1.0);
cout<<"Inited!"<<endl;
}