本文主要说明OpenGL技术中glfw的GL上下文与事件处理:
1.glfw创建GL上下文;
2.鼠标事件;
3.键盘事件;
4.文件删除事件;
5.计时操作;
OpenGL上下文创建
关于上下文
上下文的创建与释放
-
创建
- 使用
glfwCreateWindow
函数创建窗体的时候,就同时创建两两个环境:窗体与OpenGL或者OpenGL ES上下文;
- 使用
-
释放
- 上下文的释放与窗体与整个应用的释放一起,就是调用
glfwDestroyWindow
或者glfwTerminate
函数的时候;
- 上下文的释放与窗体与整个应用的释放一起,就是调用
上下文的设置
- 上下问的设置使用
glfwWindowHint
函数设置,并且在调用glfwCreateWindow
之前。
两个窗体共享上下文
- 在使用
glfwCreateWindow
创建窗体的时候,指定GLFWwindow * share
参数即可。
离屏上下文
GLFW不支持在没有关联窗口的情况下创建上下文。但是,可以使用GLFW_VISIBLE窗体创建提示创建具有隐藏窗口的上下文。
但是在Mac系统中,窗体创建的时候会自动创建菜单条,可以使用
GLFW_COCOA_MENUBAR
提示设置隐藏。
没有上下文的窗体
- 创建窗体的时候,可以不创建上下文,只要使用
GLFW_CLIENT_API
提示的值为:GLFW_NO_API
。 - 没有上下文的窗体不能传递给如下两个函数:
glfwMakeContextCurrent
glfwSwapBuffers
当前上下文
-
在进行OpenGL或OpenGL ES调用之前,需要具有正确类型的当前上下文。
- 一个上下文一次只能是单个线程的当前上下文,而一个线程一次只能有一个当前上下文。
- 在线程之间移动上下文时,必须先使旧线程上的上下文变成非当前,然后使其成为新线程上的当前上下文(否则两个线程都是当前上下文,就麻烦了)。
- 设置当前上下文,使用函数
glfwMakeContextCurrent
- 返回当前上下文,使用函数
glfwGetCurrentContext
glfwMakeContextCurrent函数说明
void glfwMakeContextCurrent ( GLFWwindow * window )
- glfwGetCurrentContext函数说明
GLFWwindow* glfwGetCurrentContext ( void )
- 下面几个函数调用,必须有当前上下文,否则会产生错误
GLFW_NO_CURRENT_CONTEXT
:- glfwSwapInterval
- glfwExtensionSupported
- glfwGetProcAddress
关于OpenGL的扩展
-
关于扩展
- OpenGL和OpenGLES的一个好处是它们的可扩展性。硬件供应商可能在其实现中包含扩展,这些扩展在新版本的OpenGL或OpenGL ES规范中包含该功能之前对API进行扩展,并且某些扩展永远不会包含在其中,并且在它们过时之前一直作为扩展保留。
- OpenGL和Direct3D比较起来,最大的一个长处就是其扩展机制。硬件厂商开发出一个新功能,可以针对新功能开发OpenGL扩展,软件开发人员通过这个扩展就可以使用新的硬件功能。所以虽然显卡的发展速度比OpenGL版本更新速度快得多,但程序员仍然可以通过OpenGL使用最新的硬件功能。而Direct3D则没有扩展机制,硬件的新功能要等到微软发布新版DirectX后才可能支持。
-
glad扩展
https://glad.dav1d.de
在上下文上开始3D绘制
- 基本步骤是:
- 创建上下文(通过创建窗体实现)
- 设置当前上下文;
- 初始化OpenGL
- 开始绘制
#include
#include
#include
#include
#include
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 创建窗体
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗体", NULL, NULL);
// 1. 第一步:设置当前上下文
glfwMakeContextCurrent(window);
// 2. 第二部:初始化OpenGL
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失败:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// 3. 设置清屏颜色
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 释放
glfwTerminate();
return 0;
}
// 编译命令:g++ -omain trangle.cpp -lglfw -lglew -framework opengl
- 运行效果:
-
键盘事件
键盘事件实现
- 键盘事件使用回调函数实现:
glfwSetKeyCallback
- 函数说明:
GLFWkeyfun glfwSetKeyCallback (
GLFWwindow * window,
GLFWkeyfun cbfun
)
- 回调函数GLFWkeyfun原型说明
typedef void(* GLFWkeyfun) (GLFWwindow *, int, int, int, int)
- 参数说明:
- window :发生事件的窗体
- key :激发的键值
- scancode :键值的系统扫描码
- action:动作GLFW_PRESS, GLFW_RELEASE or GLFW_REPEAT.
- mods: 辅助键ALT,CTRL,SHIFT,META等
- 事件实现代码
#include
#include
#include
#include
#include
void cb_key(GLFWwindow * win, int key, int code, int action, int mods){
printf("key:%d, code:%d, action:%d, mods:%d\n", key, code, action, mods);
}
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 创建窗体
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗体", NULL, NULL);
// 处理事件
glfwSetKeyCallback(window, cb_key);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失败:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// 3. 设置清屏颜色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 释放
glfwTerminate();
return 0;
}
// 编译命令:g++ -omain gl02_key_event.cpp -lglfw -lglew -framework opengl
键值定义
#define GLFW_KEY_UNKNOWN -1
#define GLFW_KEY_SPACE 32
#define GLFW_KEY_APOSTROPHE 39 /* ' */
#define GLFW_KEY_COMMA 44 /* , */
#define GLFW_KEY_MINUS 45 /* - */
#define GLFW_KEY_PERIOD 46 /* . */
#define GLFW_KEY_SLASH 47 /* / */
#define GLFW_KEY_0 48
#define GLFW_KEY_1 49
#define GLFW_KEY_2 50
#define GLFW_KEY_3 51
#define GLFW_KEY_4 52
#define GLFW_KEY_5 53
#define GLFW_KEY_6 54
#define GLFW_KEY_7 55
#define GLFW_KEY_8 56
#define GLFW_KEY_9 57
#define GLFW_KEY_SEMICOLON 59 /* ; */
#define GLFW_KEY_EQUAL 61 /* = */
#define GLFW_KEY_A 65
#define GLFW_KEY_B 66
#define GLFW_KEY_C 67
#define GLFW_KEY_D 68
#define GLFW_KEY_E 69
#define GLFW_KEY_F 70
#define GLFW_KEY_G 71
#define GLFW_KEY_H 72
#define GLFW_KEY_I 73
#define GLFW_KEY_J 74
#define GLFW_KEY_K 75
#define GLFW_KEY_L 76
#define GLFW_KEY_M 77
#define GLFW_KEY_N 78
#define GLFW_KEY_O 79
#define GLFW_KEY_P 80
#define GLFW_KEY_Q 81
#define GLFW_KEY_R 82
#define GLFW_KEY_S 83
#define GLFW_KEY_T 84
#define GLFW_KEY_U 85
#define GLFW_KEY_V 86
#define GLFW_KEY_W 87
#define GLFW_KEY_X 88
#define GLFW_KEY_Y 89
#define GLFW_KEY_Z 90
#define GLFW_KEY_LEFT_BRACKET 91 /* [ */
#define GLFW_KEY_BACKSLASH 92 /* \ */
#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */
#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */
#define GLFW_KEY_WORLD_1 161 /* non-US #1 */
#define GLFW_KEY_WORLD_2 162 /* non-US #2 */
#define GLFW_KEY_ESCAPE 256
#define GLFW_KEY_ENTER 257
#define GLFW_KEY_TAB 258
#define GLFW_KEY_BACKSPACE 259
#define GLFW_KEY_INSERT 260
#define GLFW_KEY_DELETE 261
#define GLFW_KEY_RIGHT 262
#define GLFW_KEY_LEFT 263
#define GLFW_KEY_DOWN 264
#define GLFW_KEY_UP 265
#define GLFW_KEY_PAGE_UP 266
#define GLFW_KEY_PAGE_DOWN 267
#define GLFW_KEY_HOME 268
#define GLFW_KEY_END 269
#define GLFW_KEY_CAPS_LOCK 280
#define GLFW_KEY_SCROLL_LOCK 281
#define GLFW_KEY_NUM_LOCK 282
#define GLFW_KEY_PRINT_SCREEN 283
#define GLFW_KEY_PAUSE 284
#define GLFW_KEY_F1 290
#define GLFW_KEY_F2 291
#define GLFW_KEY_F3 292
#define GLFW_KEY_F4 293
#define GLFW_KEY_F5 294
#define GLFW_KEY_F6 295
#define GLFW_KEY_F7 296
#define GLFW_KEY_F8 297
#define GLFW_KEY_F9 298
#define GLFW_KEY_F10 299
#define GLFW_KEY_F11 300
#define GLFW_KEY_F12 301
#define GLFW_KEY_F13 302
#define GLFW_KEY_F14 303
#define GLFW_KEY_F15 304
#define GLFW_KEY_F16 305
#define GLFW_KEY_F17 306
#define GLFW_KEY_F18 307
#define GLFW_KEY_F19 308
#define GLFW_KEY_F20 309
#define GLFW_KEY_F21 310
#define GLFW_KEY_F22 311
#define GLFW_KEY_F23 312
#define GLFW_KEY_F24 313
#define GLFW_KEY_F25 314
#define GLFW_KEY_KP_0 320
#define GLFW_KEY_KP_1 321
#define GLFW_KEY_KP_2 322
#define GLFW_KEY_KP_3 323
#define GLFW_KEY_KP_4 324
#define GLFW_KEY_KP_5 325
#define GLFW_KEY_KP_6 326
#define GLFW_KEY_KP_7 327
#define GLFW_KEY_KP_8 328
#define GLFW_KEY_KP_9 329
#define GLFW_KEY_KP_DECIMAL 330
#define GLFW_KEY_KP_DIVIDE 331
#define GLFW_KEY_KP_MULTIPLY 332
#define GLFW_KEY_KP_SUBTRACT 333
#define GLFW_KEY_KP_ADD 334
#define GLFW_KEY_KP_ENTER 335
#define GLFW_KEY_KP_EQUAL 336
#define GLFW_KEY_LEFT_SHIFT 340
#define GLFW_KEY_LEFT_CONTROL 341
#define GLFW_KEY_LEFT_ALT 342
#define GLFW_KEY_LEFT_SUPER 343
#define GLFW_KEY_RIGHT_SHIFT 344
#define GLFW_KEY_RIGHT_CONTROL 345
#define GLFW_KEY_RIGHT_ALT 346
#define GLFW_KEY_RIGHT_SUPER 347
#define GLFW_KEY_MENU 348
#define GLFW_KEY_LAST GLFW_KEY_MENU
修饰键定义
#define GLFW_MOD_SHIFT 0x0001
#define GLFW_MOD_CONTROL 0x0002
#define GLFW_MOD_ALT 0x0004
#define GLFW_MOD_SUPER 0x0008
#define GLFW_MOD_CAPS_LOCK 0x0010
#define GLFW_MOD_NUM_LOCK 0x0020
键值转换为扫描码
- 使用函数
- glfwGetKeyScancode函数说明
int glfwGetKeyScancode ( int key )
获取键值的状态
- 获取某个键在制定窗体最后的状态,用来判定一个键是否按下,还是释放:
glfwGetKey
。
- glfwGetKey函数说明
int glfwGetKey (
GLFWwindow * window,
int key
)
-
GLFW_STICKY_KEYS粘附键设置
如果模式是GLFW_STICKY_KEYS,则该值必须为GLFW_TRUE才能启用粘滞键,或者GLFW_FALSE才能禁用该模式。
如果启用了粘滞键,按键将确保下次调用glfwGetKey时返回GLFW_PRESS,即使在调用之前已释放该键。当您只关心按键是否已按下,而不关心按键的时间或顺序时,这一点非常有用。
设置输入模式使用:
glfwSetInputMode
glfwSetInputMode函数说明:
void glfwSetInputMode (
GLFWwindow * window,
int mode,
int value )
- 其中的mode定义只能是如下值:
- GLFW_CURSOR:这个只能设置为:GLFW_CURSOR_NORMAL,GLFW_CURSOR_HIDDEN,GLFW_CURSOR_DISABLED。
- GLFW_STICKY_KEYS,
- GLFW_STICKY_MOUSE_BUTTONS,
- GLFW_LOCK_KEY_MODS,
- GLFW_RAW_MOUSE_MOTION
文件输入
- 使用glfwSetCharCallback函数实现文本输入,既输入的是文本,包含unicode字符(一般是UTF-8编码)。
- glfwSetCharCallback函数说明:
GLFWcharfun glfwSetCharCallback (
GLFWwindow * window,
GLFWcharfun cbfun
)
- 回调函数GLFWcharfun原型说明
typedef void(* GLFWcharfun) (GLFWwindow *, unsigned int)
- 文本输入的例子代码
- 包含UTF-8字符的输出;
#include
#include
#include
#include
#include
#include
#include
using namespace std;
// 把codeppint转换为native字符。
void utf8chr(int cp, char c[5]){ //一个unicode最多占5个字节。
// char c[5]={ 0x00,0x00,0x00,0x00,0x00 };
if (cp<=0x7F) { // 127的常规字符
c[0] = cp;
}
else if(cp<=0x7FF) {
c[0] = (cp>>6)+192;
c[1] = (cp&63)+128;
}
else if(0xd800<=cp && cp<=0xdfff) {
// 无效utf-8的codepoint区
} //invalid block of utf8
else if(cp<=0xFFFF) {
c[0] = (cp>>12)+224;
c[1]= ((cp>>6)&63)+128;
c[2]=(cp&63)+128; }
else if(cp<=0x10FFFF) {
c[0] = (cp>>18)+240;
c[1] = ((cp>>12)&63)+128;
c[2] = ((cp>>6)&63)+128;
c[3]=(cp&63)+128;
}
}
void cb_char(GLFWwindow *win, unsigned int ch){
char c[5]={ 0x00,0x00,0x00,0x00,0x00 }; // 一个unicode字符最多4字节,包含一个空终止符。
utf8chr(ch, c);
printf("输入的字符:%s\n", c);
}
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 创建窗体
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗体", NULL, NULL);
glfwSetCharCallback (window, cb_char);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失败:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// 3. 设置清屏颜色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 释放
glfwTerminate();
return 0;
}
// 编译命令:g++ -omain gl04_char.cpp -lglfw -lglew -framework opengl
- 其中utf8chr函数是实现把codepoint转换为本地字符串。
- codepoint转换为本地字符串最多4字节就是int32整数,当然使用5的长度是保证最后那个NULL字符。
键的名字
- 上面对codepint解码,如果不了解codeoint与unicode,不了解utf-8的编码规则,一般不太容易理解。
- GLFW提供函数处理:
glfwGetKeyName
- glfwGetKeyName函数说明
const char* glfwGetKeyName (
int key,
int scancode
)
- 如果key是GLFW_KEY_UNKNOWN,则对scancode解释。对key解释,则scancode为0。
- glfwGetKeyName函数使用例子
// glfwSetKeyCallback(window, cb_key);
void cb_key(GLFWwindow * win, int key, int code, int action, int mods){
const char *str_ch = glfwGetKeyName(key, code);
printf("glfwGetKeyName:%s\n", str_ch);
}
鼠标事件
光标位置
- 鼠标的光标位置通过回调传递,回调函数通过函数
glfwSetCursorPosCallback
设置; - 也可以使用函数
glfwGetCursorPos
直接获取鼠标位置。
- glfwSetCursorPosCallback函数说明
GLFWcursorposfun glfwSetCursorPosCallback (
GLFWwindow * window,
GLFWcursorposfun cbfun
)
- 回调函数GLFWcursorposfun的原型说明
typedef void(* GLFWcursorposfun) (GLFWwindow *, double, double)
- glfwGetCursorPos函数说明
void glfwGetCursorPos (
GLFWwindow * window,
double * xpos,
double * ypos
)
光标模式
- glfwSetInputMode函数可以控制鼠标光标模式
void glfwSetInputMode (
GLFWwindow * window,
int mode,
int value
)
- 其中mode设置为光标的模式,光标模式包含3个值
- GLFW_CURSOR,其值为:
- GLFW_CURSOR_NORMAL:正常
- GLFW_CURSOR_HIDDEN:隐藏
- GLFW_CURSOR_DISABLED:隐藏和抓取光标,提供虚拟和无限的光标移动。
- GLFW_CURSOR,其值为:
鼠标原生动作
禁用光标时,可以启用原生(未缩放和未加速)鼠标运动(如果可用)。
原生鼠标运动更接近鼠标在曲面上的实际运动。它不受应用于桌面光标运动的缩放和加速的影响。该处理适用于光标,而原生运动更适合控制例如3D相机。因此,只有在禁用光标时才提供原生鼠标运动。
调用glfwRawMouseMotionSupported函数检查当前机器是否提供原始运动,并将GLFW_RAW_MOUSE_MOTION输入模式设置为启用。
默认情况下禁用。
光标位置与模式的使用例子
#include
#include
#include
#include
#include
#include
void cb_pos(GLFWwindow *win, double x, double y){
char title[50];
bzero(title, sizeof(title));
sprintf(title, "坐标:(%8.2f,%8.2f)", x, y);
glfwSetWindowTitle(win, title);
double xpos, ypos;
glfwGetCursorPos(win, &xpos, &ypos); //与上面传递的位置完全一样。
printf("坐标:(%8.2f,%8.2f)\n", xpos, ypos);
}
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 创建窗体
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗体", NULL, NULL);
// 鼠标光标模式
// glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
if (glfwRawMouseMotionSupported()){
printf("原生鼠标模式\n");
glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
}else{
printf("原生不支持鼠标模式\n");
}
// 处理事件
glfwSetCursorPosCallback(window, cb_pos);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失败:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// 3. 设置清屏颜色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 释放
glfwTerminate();
return 0;
}
// 编译命令:g++ -omain gl06_cursor.cpp -lglfw -lglew -framework opengl
光标对象
创建光标
- 光标对象是一个结构体
typedef struct GLFWcursor GLFWcursor
创建标准光标
- 创建标准光标使用glfwCreateStandardCursor函数
- glfwCreateStandardCursor函数说明
GLFWcursor* glfwCreateStandardCursor(int shape)
- 创建好的光标使用下面的设置光标函数设置即可使用。
- 标准光标类型
#define GLFW_ARROW_CURSOR 0x00036001
#define GLFW_IBEAM_CURSOR 0x00036002
#define GLFW_CROSSHAIR_CURSOR 0x00036003
#define GLFW_HAND_CURSOR 0x00036004
#define GLFW_HRESIZE_CURSOR 0x00036005
#define GLFW_VRESIZE_CURSOR 0x00036006
创建定制光标
- 自定义光标是使用glfwCreateCursor函数创建的,它返回创建的光标对象的句柄。
- glfwCreateCursor函数说明
GLFWcursor* glfwCreateCursor (
const GLFWimage * image,
int xhot,
int yhot //光标的参照点(热点hotspot)
)
释放光标
- 使用glfwDestroyCursor函数释放光标
void glfwDestroyCursor ( GLFWcursor * cursor )
设置窗体光标
- 当创建好光标后,就可以设置光标来使用,该函数为
glfwSetCursor
:
- glfwSetCursor函数说明
void glfwSetCursor (
GLFWwindow * window,
GLFWcursor * cursor
)
使用光标对象的例子
#include
#include
#include
#include
#include
#include
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 创建窗体
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗体", NULL, NULL);
// 创建光标对象
GLFWcursor *cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
// 创建一个定制光标
unsigned char pixels[16 * 16 * 4]; // 光标的图像数据
memset(pixels, 0xff, sizeof(pixels)); // 图像结构体
GLFWimage image;
image.width = 16;
image.height = 16;
image.pixels = pixels;
GLFWcursor* c_cursor = glfwCreateCursor(&image, 0, 0); // 使用图像创建光标
// 设置光标
// glfwSetCursor(window, cursor);
glfwSetCursor(window, c_cursor);
// 释放光标
// glfwDestroyCursor(cursor); // 释放光标,光标恢复成缺省光标
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失败:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// 3. 设置清屏颜色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 释放
glfwTerminate();
return 0;
}
// 编译命令:g++ -omain gl07_cursor_object.cpp -lglfw -lglew -framework opengl
光标进出窗体事件
- 光标进出状态通过两种方式:
- 回调的事件方式:
glfwSetCursorEnterCallback
; - 查询获取方式:
glfwGetWindowAttrib
+GLFW_HOVERED
;
- 回调的事件方式:
- glfwSetCursorEnterCallback函数说明
GLFWcursorenterfun glfwSetCursorEnterCallback (
GLFWwindow * window,
GLFWcursorenterfun cbfun
)
- 回调函数GLFWcursorenterfun原型说明
typedef void(* GLFWcursorenterfun) (GLFWwindow *, int)
// 第二个参数是GLFW_TRUE:进,否则GLFW_FALSE:出
鼠标按钮输入
鼠标按钮事件处理
- 这是通过回调函数的方式实现:
glfwSetMouseButtonCallback
- glfwSetMouseButtonCallback函数说明
GLFWmousebuttonfun glfwSetMouseButtonCallback (
GLFWwindow * window,
GLFWmousebuttonfun cbfun
- GLFWmousebuttonfun回调函数原型说明
typedef void(* GLFWmousebuttonfun) (GLFWwindow *, int, int, int)
// 第二个参数:button
// 第三个参数:action:GLFW_PRESS 或者 GLFW_RELEASE
// 第四个参数:mods:辅助键状态
- 鼠标按钮定义
#define GLFW_MOUSE_BUTTON_1 0
#define GLFW_MOUSE_BUTTON_2 1
#define GLFW_MOUSE_BUTTON_3 2
#define GLFW_MOUSE_BUTTON_4 3
#define GLFW_MOUSE_BUTTON_5 4
#define GLFW_MOUSE_BUTTON_6 5
#define GLFW_MOUSE_BUTTON_7 6
#define GLFW_MOUSE_BUTTON_8 7
#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8
#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1
#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2
#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3
鼠标按钮的轮询
- 就是鼠标输入的另外一种方式:轮询,不是听过事件;而是通过函数调用来查询状态。
- 查询函数是:
glfwGetMouseButton
- 查询函数是:
- glfwGetMouseButton函数说明
int glfwGetMouseButton (
GLFWwindow * window,
int button
)
-
返回值是:
- GLFW_PRESS :按下过;
- GLFW_RELEASE:没有按下过;
参数button就是需要对按下判定的按钮。
- 为了防止在轮询的时候,按下动作已经完成,这样轮询容易错失那次鼠标按钮操作,解决这个问题与键盘的处理一样,通过设置输入模式来解决。
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, GLFW_TRUE);
鼠标滚轮输入
- 鼠标滚轮事件也是回调函数的方式来实现输入与处理。
- 函数是:glfwSetScrollCallback
- glfwSetScrollCallback 函数说明
GLFWscrollfun glfwSetScrollCallback (
GLFWwindow * window,
GLFWscrollfun cbfun
)
- 回调函数GLFWscrollfun原型说明
typedef void(* GLFWscrollfun) (GLFWwindow *, double, double)
鼠标进出、滚轮与按钮事件的例子
#include
#include
#include
#include
#include
#include
// 鼠标进出回调触发函数
void cursor_enter_callback(GLFWwindow *win, int enter_or_leave){
if (enter_or_leave){
printf("鼠标进入!\n");
}
else{
printf("鼠标出去!\n");
}
}
// 鼠标按钮
void mouse_button_callback(GLFWwindow *win, int button, int action, int mods){
printf("鼠标按钮:button=%d,action=%d,mods=%d\n", button, action, mods);
}
// 鼠标滚轮
void scroll_callback(GLFWwindow *win, double xoffset, double yoffset){
printf("鼠标滚轮:xoffset=%8.2f,yoffset=%8.2f\n", xoffset, yoffset);
}
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 创建窗体
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗体", NULL, NULL);
// 鼠标的粘附输入模式
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, GLFW_TRUE);
// 鼠标进出判定
glfwSetCursorEnterCallback(window, cursor_enter_callback);
// 鼠标按钮操作判定
glfwSetMouseButtonCallback(window, mouse_button_callback);
// 鼠标滚轮
glfwSetScrollCallback(window, scroll_callback);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失败:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
// move轮询
if (glfwGetWindowAttrib(window, GLFW_HOVERED)){
printf("轮询:进入\n");
}
else{
printf("轮询:出去\n");
}
//按键轮询
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
if(state == GLFW_PRESS){
printf("左键按下!\n");
}
// 3. 设置清屏颜色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 释放
glfwTerminate();
return 0;
}
// 编译命令:g++ -omain gl08_button_scroll_move.cpp -lglfw -lglew -framework opengl
文件删除事件
- 一旦用户删除文件,可以通过函数
glfwSetDropCallback
处理;
- glfwSetDropCallback函数说明
GLFWdropfun glfwSetDropCallback (
GLFWwindow * window,
GLFWdropfun cbfun
)
- 回调函数GLFWdropfun原型说明
typedef void(* GLFWdropfun) (GLFWwindow *, int, const char **)
// 第二个参数:count:删除文件个数
// 第三个参数:paths:返回删除的文件列表
时间计时
- GLFW提供四个与时间有关的函数:
- glfwGetTime:获取从glfwInit初始化以来的时间,单位是秒;
- glfwSetTime:修改从glfwInit初始化以来的时间,单位是秒;
- glfwGetTimerValue:获取真实的定时器的时间值,单位是秒;
- glfwGetTimerFrequency:获取时间频率;
- 注意:
- 四个函数比较简单,这里不详细说明,下面是使用例子。
#include
#include
#include
#include
#include
#include
int main(int argc, char const *argv[]){
// 初始化
glfwInit();
// 1. 初始化opengl
// 创建窗体
GLFWwindow *window = glfwCreateWindow(800, 600, "OpenGL的UI窗体", NULL, NULL);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK){
printf("OpenGL初始化失败:glew\n");
exit(-1);
}
while (! glfwWindowShouldClose(window)){
double seconds = glfwGetTime();
uint64_t value = glfwGetTimerValue();
uint64_t freqency = glfwGetTimerFrequency();
printf("相对时间:%8.2f,真实时间:%lld,频率:%lld\n", seconds, value, freqency);
glfwSetTime(0.0);
// 3. 设置清屏颜色
glClearColor(0.0f, 0.6f, 0.6f, 1.0f);
// 4. 清屏
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
}
// 释放
glfwTerminate();
return 0;
}
// 编译命令:g++ -omain gl09_timer.cpp -lglfw -lglew -framework opengl