在 OCaml 中使用 openGL 和 SDL 处理键盘时出现问题
我在使用 SDL(仅适用于键盘事件)和 openGL(为了显示图形,我计划显示 3d 图形)处理键盘事件时遇到问题。当我使用 Sdevent.poll 时,没有任何反应,并且我无法使用 wait_event,因为我必须实时显示。我几乎尝试了所有我认为的方法,但没有成功,你是我唯一的希望! ^^
这是我的源代码(它只是一个旋转的方块......)
let rotate = ref 1.0
let _ = Sdl.init [`VIDEO] ; at_exit Sdl.quit
let key_handler k = match k with
| {Sdlevent.keysym=Sdlkey.KEY_ESCAPE} ->
print_endline "I'll miss you so much..." ;
| {Sdlevent.keysym=Sdlkey.KEY_SPACE} ->
print_endline "UP" ;
| {Sdlevent.keysym=Sdlkey.KEY_DOWN} ->
print_endline "DOWN";
| _ -> ()
let renderScene () =
let current_time = ref (Sdltimer.get_ticks()) in
GlClear.clear[`color;`depth];
GlMat.rotate3 (!rotate) (0.0,0.0,1.0);
GlDraw.begins `quad_strip;
GlDraw.color (1.0, 0.0, 0.0);
GlDraw.vertex3 (-0.5, 0.5, 0.0);
GlDraw.vertex3 (-0.5, -0.5, 0.0);
GlDraw.color (0.0, 0.0, 1.0);
GlDraw.vertex3 (0.5, 0.5, 0.0);
GlDraw.vertex3 (0.5,-0.5, 0.0);
GlDraw.ends ();
current_time := Sdltimer.get_ticks() - !current_time;
if(!current_time < 10) then
Sdltimer.delay (10 - !current_time);
Glut.swapBuffers();
Glut.postRedisplay();
begin
match Sdlevent.poll () with
| Some (Sdlevent.KEYDOWN k) ->
print_endline "nope"; key_handler k
| None | _ -> print_endline "nopeee";
end;
Gl.flush();;
let () =
ignore(Glut.init Sys.argv);
Glut.initDisplayMode ~alpha:true ~double_buffer:true ~depth:true ();
Glut.initWindowPosition ~x:100 ~y:100;
Glut.initWindowSize ~w:500 ~h:500;
ignore(Glut.createWindow ~title:"3DMapPro - Edition Expert Business 2012");
GlClear.color(1.,1.,1.);
Glut.displayFunc ~cb:(renderScene);
print_string "oui";
Glut.keyboardFunc (fun ~key ~x ~y -> if key=27 then exit 0);
Glut.mainLoop();;
由于我不明白如何在 stackoverflow 上正确发布代码,您还可以在这里找到我的源代码,缩进并突出显示: Pastebin
I've a problem handling keyboards events using SDL (only for keyboard events) and openGL (to display graphics, I'm planning to display 3d graphics). When I use Sdlevent.poll nothing happen and I can't use wait_event because I've to display in real time. I've tried almost everyting I thinks and NOTHING has been successful, you are my only hope ! ^^
Here is my source code (it's just a spinning square ...)
let rotate = ref 1.0
let _ = Sdl.init [`VIDEO] ; at_exit Sdl.quit
let key_handler k = match k with
| {Sdlevent.keysym=Sdlkey.KEY_ESCAPE} ->
print_endline "I'll miss you so much..." ;
| {Sdlevent.keysym=Sdlkey.KEY_SPACE} ->
print_endline "UP" ;
| {Sdlevent.keysym=Sdlkey.KEY_DOWN} ->
print_endline "DOWN";
| _ -> ()
let renderScene () =
let current_time = ref (Sdltimer.get_ticks()) in
GlClear.clear[`color;`depth];
GlMat.rotate3 (!rotate) (0.0,0.0,1.0);
GlDraw.begins `quad_strip;
GlDraw.color (1.0, 0.0, 0.0);
GlDraw.vertex3 (-0.5, 0.5, 0.0);
GlDraw.vertex3 (-0.5, -0.5, 0.0);
GlDraw.color (0.0, 0.0, 1.0);
GlDraw.vertex3 (0.5, 0.5, 0.0);
GlDraw.vertex3 (0.5,-0.5, 0.0);
GlDraw.ends ();
current_time := Sdltimer.get_ticks() - !current_time;
if(!current_time < 10) then
Sdltimer.delay (10 - !current_time);
Glut.swapBuffers();
Glut.postRedisplay();
begin
match Sdlevent.poll () with
| Some (Sdlevent.KEYDOWN k) ->
print_endline "nope"; key_handler k
| None | _ -> print_endline "nopeee";
end;
Gl.flush();;
let () =
ignore(Glut.init Sys.argv);
Glut.initDisplayMode ~alpha:true ~double_buffer:true ~depth:true ();
Glut.initWindowPosition ~x:100 ~y:100;
Glut.initWindowSize ~w:500 ~h:500;
ignore(Glut.createWindow ~title:"3DMapPro - Edition Expert Business 2012");
GlClear.color(1.,1.,1.);
Glut.displayFunc ~cb:(renderScene);
print_string "oui";
Glut.keyboardFunc (fun ~key ~x ~y -> if key=27 then exit 0);
Glut.mainLoop();;
Since I don't understand how to post code properly on stackoverflow, you can also find my source code well indented and highlighted here : Pastebin
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先要做的事情是:您将 GLUT 与 SDL 混合在一起,两者都会在处理窗口和输入事件处理方面展开斗争。选择其中之一。 GLUT 不是 OpenGL 的一部分
我想你是从一些教程中了解到这一点的。关键行是这一行,它使用了 GLUT:
这里在原位创建了一个 lambda(=匿名)函数,并将其传递给
Glut.keyboadFunc
作为处理程序。如果传递 ESC,此 lambda 将调用exit 0
。要解决此问题,您首先需要摆脱 GLUT(所有以Glut.
开头的语句)并将其替换为 SDL 对应项。此外,您将 SDL 事件轮询放置在渲染函数中。这是错误的!事件轮询应该发生,目前是
Glut.mainLoop()
。此外,您的渲染功能缺乏适当的视口、投影和模型视图设置,这也需要修复。
First things first: You're mixing GLUT with SDL, both will battle for dealing with windowing and input event handling. Settle for one of those. GLUT is not part of OpenGL
I presume you have this from some tutorial. The key line is this one, which uses GLUT:
Here a lambda (=anonymous) function is created in situ and passed to
Glut.keyboadFunc
as handler. This lambda will callexit 0
if ESC is passed. To fix this you first need to get rid of GLUT (all statements beginning withGlut.
) and replace it with SDL counterparts.Furthermore you placed the SDL event polling in the render function. This is just WRONG! Event polling should happen, where at the moment
Glut.mainLoop()
is.Also your render function lacks proper viewport, projection and modelview setup, this needs fixing as well.
在我看来,SDL 和 Glut 都认为他们应该读取密钥。因此,也许 Glut 正在获胜而 SDL 正在失败。如果按 ESC(代码为 27),程序会退出吗?
It looks to me like both SDL and Glut think they are supposed to be reading the keys. So maybe Glut is winning and SDL is losing. Does the program exit if you hit ESC (which has a code of 27)?