在 OCaml 中使用 openGL 和 SDL 处理键盘时出现问题

发布于 2024-12-06 21:29:35 字数 1918 浏览 1 评论 0原文

我在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

舞袖。长 2024-12-13 21:29:35

首先要做的事情是:您将 GLUT 与 SDL 混合在一起,两者都会在处理窗口和输入事件处理方面展开斗争。选择其中之一。 GLUT 不是 OpenGL 的一部分

我想你是从一些教程中了解到这一点的。关键行是这一行,它使用了 GLUT:

Glut.keyboardFunc (fun ~key ~x ~y -> if key=27 then exit 0);

这里在原位创建了一个 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:

Glut.keyboardFunc (fun ~key ~x ~y -> if key=27 then exit 0);

Here a lambda (=anonymous) function is created in situ and passed to Glut.keyboadFunc as handler. This lambda will call exit 0 if ESC is passed. To fix this you first need to get rid of GLUT (all statements beginning with Glut.) 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.

╰つ倒转 2024-12-13 21:29:35

在我看来,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)?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文