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;
}
时间: 2024-10-16 04:33:30

OpenGL编程 基础篇(四)与鼠标的交互的相关文章

OpenGL编程 基础篇(五)世界窗口和视口

一.基本定义 世界窗口:在世界坐标系中定义一个对齐的矩形(aligned rectangle,即矩阵的边与坐标轴平行)的窗口,这个世界窗口外的部分被裁减并不被绘制.OpenGL会自动地做剪裁. 视口:在显示器的屏幕窗口上定义一个对齐的矩形的视口,OpenGL会自动建立世界窗口和视口的变换(包括缩放和平移).当世界窗口中所有对象都被绘制时,对象在世界窗 口中的部分会被自动地映射到视口中----换句话说,被映射到屏幕坐标中,即像素在显示器上的坐标. 二.相关函数介绍 1.对于二维绘图来说,世界窗口由

OpenGL编程 基础篇(六)OpenGL中几种光照参数

一.定义 1.GL_AMBIENT:环境光,经过很多次反射后最终遗留在环境中的光线强度(颜色). 2.GL_DIFFUSE:漫反射,表示光线照射到该材质上,经过漫反射后形成的光线强度(颜色). 3.GL_SPECULAR:镜面反射,表示光线照射到该材质上,经过镜面反射后形成的光线强度(颜色). 注:通常,GL_AMBIENT和GL_DIFFUSE都取相同的值,可以达到比较真实的效果.使用GL_AMBIENT_AND_DIFFUSE可以同时设置GL_AMBIENT和GL_DIFFUSE属性. 4.

OpenGL编程 基础篇(七)对象的变换——用实心体绘制3D场景

1.函数介绍 GLUT提供几种现成的对象,包括球体.圆锥体.圆环面.5个柏拉图立体,以及著名的茶壶.每个形状都可以作为一种线框的模型,也可以作为一种实心模型,每个面均已覆盖上材质. 以下列表是用于绘制这些对象的函数. void glutWireSphere(GLdouble radius, GLint slices, GLint stacks); 线框球 void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks); 实心球

Linux中的shell脚本编程——基础篇

概述: shell脚本在Linux系统管理员的运维工作中非常重要.shell脚本能够帮助我们很方便的管理服务器,因为我们可以指定一个任务计划,定时的去执行某一个脚本以满足我们的需求.本篇将从编程基础.脚本基本格式.变量.运算.条件测试这几个方面详细介绍shell脚本编程的基础内容,也是我们必须要掌握熟练的内容. 一.编程环境 1.程序:指令+数据 程序编程的风格有两种: 过程式:以指令为中心,数据服务与指令 对象式:以数据为中心,指令服务于数据 2.程序的执行方式: □计算机:只能识别二进制文件

Hybrid APP基础篇(四)-&gt;JSBridge的原理

说明 JSBridge实现原理 目录 前言 参考来源 前置技术要求 楔子 原理概述 简介 url scheme介绍 实现流程 实现思路 第一步:设计出一个Native与JS交互的全局桥对象 第二步:JS如何调用Native 第三步:Native如何得知api被调用 第四步:分析url-参数和回调的格式 第五步:Native如何调用JS 第六步:H5中api方法的注册以及格式 进一步完善JSBridge方案 思路 实现 注意 完整的JSBridge 完整调用流程图 另外实现:不采用url sche

shell 脚本编程基础篇

一级标题 二级标题 1.编程基础 Linus:Talk is cheap, show me the code 程序组成 程序:算法+数据结构 数据:是程序的核心 算法:处理数据的方式 数据结构:数据在计算机中的类型和组织方式 面向过程语言 做一件事情,排出个步骤,第一步干什么,第二步干什么,如果出现情况A,做什么处理,如 果出现了情况B,做什么处理 问题规模小,可以步骤化,按部就班处理 以指令为中心,数据服务于指令 C,shell 面向对象语言 一种认识世界.分析世界的方法论.将万事万物抽象为各

JavaScript基础篇(四)— — 函数

一.函数基础 ??1.返回值:如果某个函数没有显式的return返回值,默认它的返回值为undefined ??2.参数:内建变量arguments,能返回函数所接收的所有参数 ???? ??3.预定义(内建)函数 -- isNaN: ????a.检测parseInt / parseFloat调用是否成功. ???? ????b.NaN不存在等值的概念, 也就是说表达式NaN === NaN 返回的是false 二.函数的变量作用域 ??1.变量提升:函数域优先于全局域,所有局部a会覆盖掉所有与

Shell编程基础篇-上

1.1 前言 1.1.1 为什么学Shell Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具, Linux/UNIX系统的底层及基础应用软件的核心大都涉及Shell脚本的内容.每一个合格 的Linux系统管理员或运维工程师,都需要能够熟练地编写Shell脚本语言,并能够阅 读系统及各类软件附带的Shell脚本内容.只有这样才能提升运维人员的工作效率,适 应曰益复杂的工作环境,减少不必要的重复工作,从而为个人的职场发展奠定较好的基础 1.1.2 什么是shell

Python Socket编程基础篇

Socket网络编程 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用打开.读写.关闭模式来操作.socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO.打开.关闭) socket和file的区别: file模块是针对某个指定