OpenGL編程 基礎篇(四)與鼠標的交互


當用戶按下或釋放鼠標按鈕、按下按鈕時移動鼠標或按下和松開鍵盤按鍵時,就會產生一個相關事件。程序員可以用每類事件注冊一個回調函數,例如使用如下函數:

  • glutMouseFunc(myMouse):利用按下或釋放鼠標按鈕時發生的事件來注冊myMouse
  • glutMotionFunc(myMovedMouse):利用按下按鈕同時移動鼠標的事件來注冊myMovedMouse
  • glutKeyboardFunc(myKeyboard):利用按下和松開鍵盤按鍵的事件來注冊myKeyboard

1.用鼠標交互

回調函數的名字可以隨便起,但是一定要帶4個參數,其原型如下:

void myMouse(int button,int state,int x,int y); 當鼠標事件發生時,系統會調用注冊的函數,並向其提供這些參數值。

 button的值可能是下面明顯含義中的一個:GLUT_LEFT_BUTTON、GLUT_MIDDLE_BUTTON、GLUT_RIGHT_BUTTON

 state 的值可能是:GLUT_UP、GLUT_DOWN

x和y的值指明事件發生時鼠標的位置(注意:x是距離窗口左邊的像素數、y是距離窗口頂端的像素數)

時間處理器本身並不引起屏幕的重新繪制事件。因此,為了看到鼠標的效果,鼠標處理器應該調用glutPostRedisplay()

#include "stdafx.h"
#include <cstdlib>
#include <gl\glut.h>
const int screenWidth = 600;
const int screenHeight = 480;
class GLintPoint
{
public:
    GLint x;
    GLint y;
    GLintPoint(){
        x = 0; y = 0;
    }
    GLintPoint(GLint a, GLint b){
        x = a;
        y = b;
    }
};
void myInit(){
    glClearColor(1.0, 1.0, 1.0, 0.0);
    glColor3f(0.0f, 0.0f, 0.0f);
    glPointSize(2.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, (GLdouble)screenWidth, 0.0, (GLdouble)screenHeight);
}

void drawDot(GLint x, GLint y){
    glBegin(GL_POINTS);
    glVertex2i(x, y);
    glEnd();
}
void myDisplay(GLintPoint corner[3]){  //繪制Sierrapinski墊片的函數,參數為三個坐標點
    glClear(GL_COLOR_BUFFER_BIT);
    int index = rand() % 3;
    GLintPoint point = corner[index];
    drawDot(point.x, point.y);
    for (int i = 0; i < 55000; i++){
        index = rand() % 3;
        point.x = (point.x + corner[index].x) / 2;
        point.y = (point.y + corner[index].y) / 2;
        //printf("%d %d\n", point.x, point.y);
        drawDot(point.x, point.y);
    }
    glFlush();
}
//Simple One 用鼠標放置點,用戶每次按下左鍵時,就會在屏幕窗口鼠標所在位置繪制出一個點;如果用戶按下右鍵,就改變窗口背景顏色
void myMouse(int button, int state, int x, int y){
    if (state == GLUT_DOWN){
        if (button == GLUT_LEFT_BUTTON){
            drawDot(x, screenHeight - y);
            glFlush();
        }
        else if (button == GLUT_RIGHT_BUTTON){
            glClearColor(1.0f,0.0f,0.0f,0.0f);
            glClear(GL_COLOR_BUFFER_BIT);
            glFlush();
        }
    }
    return;
}
//Sierpinski 用鼠標控制Sierpinski墊片
void myMouseForSierpinski(int button, int state, int x, int y)
{

    static GLintPoint corner[3];
    static int numCorners = 0;
    if (state == GLUT_DOWN){
        if (button == GLUT_LEFT_BUTTON){
            corner[numCorners].x = x;
            corner[numCorners].y = screenHeight - y;
            if (++numCorners == 3){
                myDisplay(corner);
                numCorners = 0;
            }
        }
    }
    else if (button == GLUT_RIGHT_BUTTON){
        glClear(GL_COLOR_BUFFER_BIT);
        glFlush();
    }
}
void myDis(){}
int main(int argc, char **argv){

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(screenWidth, screenHeight);
    glutCreateWindow("Mouse Sierpinski");

    glutMouseFunc(myMouseForSierpinski);
    //glutMouseFunc(myMouse);
    glutDisplayFunc(myDis);
    myInit();
    glutMainLoop();
    return 0;
}

 2.用鍵盤交互

回調函數的名字可以隨便起,其原型如下:

void myKeyBoard(unsigned int key,int x,int y); 當鍵盤事件發生時,系統會調用注冊的函數,並向其提供這些參數值。

按鍵的值是所按鍵的ASCII值,數值x和y指示事件發生時鼠標所在的位置(y是距離窗口頂端的像素個數)

大多數myKeyBoard()函數都由很長的switch case語句組成

樣例:按下p鍵會在鼠標位置上繪制一個點;按下左箭頭會在某個全局列表中添加一個點,但是不繪圖;按下E會退出程序。

如果用戶一直按着p鍵並移動鼠標,就會產生一個快速點序列,這就是“徒手”繪圖。

void myKeyboard(unsigned char key,int mouseX,int mouseY){
GLint x = mouseX;
GLint y = mouseY;
    switch(key)
    {
        case 'p':
            drawDot(x,y);
            break;
        case 'E':
            exit(-1);
        case GLUT_KEY_LEFT:List[++last].x = x;
                           List[last].y = y;
                           break;
        default:
            break;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM