opengl - 我现在已经为 Glut Window 渲染了一个球体,如何让它随键盘移动?

标签 opengl emacs common-lisp glut game-physics

<分区>

剪切并粘贴 cl-glut-examples 代码,我在显示器上渲染了一个球体。现在如何使用键盘在 x、y 和 z 轴上移动它。还有一个在线资源可以学习 CL-OpenGL 中的游戏编程,或者如何制作墙壁、泥土、房屋和角色之类的东西,这样我就可以创建一个 3D 世界并在其中移动角色并为其设计游戏逻辑。

到目前为止,这是我的代码:

(defclass glut-teapot-window (glut:window)
()
(:default-initargs :width 948 :height 990 :title "glut-teapot.lisp" 
                  :mode '(:single :rgb :depth)))

(defmethod glut:display-window :before ((window glut-teapot-window))
(gl:clear-color 0 0 0 0)
(gl:cull-face :back)
(gl:depth-func :less)
(gl:disable :dither)
(gl:shade-model :smooth)
(gl:light-model :light-model-local-viewer 1)
(gl:color-material :front :ambient-and-diffuse)
(gl:enable :light0 :lighting :cull-face :depth-test))

(defmethod glut:display ((window glut-teapot-window))
(gl:load-identity)
(gl:translate 0 0 -5)
(gl:rotate 100 1 1 0)
(gl:light :light0 :position '(6000 1000 15 0))
(gl:light :light0 :position '(2000 300 3000 0))
(gl:clear :color-buffer :depth-buffer)
(gl:color 1 1 1)
(gl:front-face :cw)
(glut:Solid-Sphere 1 10 10)
(gl:front-face :ccw)
(gl:flush))

(defmethod glut:reshape ((window glut-teapot-window) width height)
(gl:viewport 0 0 width height)
(gl:matrix-mode :projection)
(gl:load-identity)
(glu:perspective 50 (/ width height) 0.5 20)
(gl:matrix-mode :modelview)
(gl:load-identity))

(defmethod glut:keyboard ((window glut-teapot-window) key x y)
(declare (ignore x y))
(when (eql key #\Esc)
(glut:destroy-current-window)))

(defun glut-teapot ()
(glut:display-window (make-instance 'glut-teapot-window)))
(glut-teapot)

最佳答案

因为我不知道您使用 opengl 的经验,所以我打算在一年前为我写下这个答案(当时我对 opengl 一无所知并且正在尝试学习使用 common lisp)。

cl-opengl 库是 opengl 的一个相当紧密的包装器,我的意思是大多数 opengl 函数在 cl-opengl 中都有一个直接等效项。这很好,因为这意味着您将能够使用 c 和 c++ 学习 opengl 的在线教程,并且只需要一点精神压力,就可以将它们转换为 lisp。

它作为 opengl 的一个非常紧密的包装器的缺点是 opengl 不是很 lispy,我的意思是好的 opengl 代码的风格与好的 lisp 代码非常不同。不过,一旦您掌握了 cl-opengl 的窍门,这绝对是可以改进的。

接下来,opengl 是一个库,其中包含两种截然不同的范例。有旧款 opengl(使用gl-begin和gl-end)和基于着色器的新型opengl可能是你想要的,如果你以后想做花哨的效果!痛苦的是,大多数好的在线教程都是针对旧式 opengl 的,或者以一种我觉得非常困惑的方式混合了两者。因此,我个人建议使用以下教程来学习现代 opengl: http://www.arcsynthesis.org/gltut/

一旦您完成了前 4 章,您就会对 opengl 有足够的了解,从而能够毫不费力地使用 opengl wiki。我这么说是因为起初我发现 opengl 语言 wiki 真的很困惑,因为我不知道所有信息应该如何组合在一起。

现在进入 GLUT。 GLUT 很酷……但它很快就会变得非常有限。我真的建议切换到 SDL。幸运的是,一些才华横溢的人已经使 lisp 中的 SDL 非常适合在 common-lisp 中使用,并将其称为 lispbuilder-sdl。 http://code.google.com/p/lispbuilder/wiki/LispbuilderSDL

好的,那么你应该如何开始呢?:

  • 获取 quicklisp:我假设您已经在使用它,但如果没有,请立即获取!它使获取 common lisp 的最新软件包变得非常容易。 http://www.quicklisp.org/beta/
  • 接下来,获取 lispbuilder (ql:quickload :lispbuilder-sdl)
  • 使用 arcsynthesis 教程熟悉 opengl。这确实是让我理解编写现代 opengl 代码所需的最佳方式。
  • 用 lisp 编写 arcsynthesis 教程中的示例。
  • 制作一些函数和宏,使您的 opengl 在 lisp 中更好地工作。

在这条路上我只比你早几个月,开始真的很痛苦,但完全值得。如果您精通 opengl,我很抱歉,因此这个答案对您来说太基础了!如果是这样,请告诉我,我会尝试提供更好的答案。

下面是在 SDL 中建立 opengl 窗口和上下文、处理事件(您的用户输入将在此处)和重绘框架(尚无可绘制但您将使用来自圆弧合成教程!)。

我还添加了一个辅助函数和宏。首先是“可继续”,这意味着如果其中的代码发生错误,错误结果中将有一个选项可以继续程序(非常方便,这样您就不必一次又一次地启动演示)。还有更新 swank,这意味着即使在演示运行时你仍然可以使用 Slime(你正在使用 slime 对吗?如果没有得到它!)

(defun init ()
  (print 'initialise-stuff-here))

(defun draw ()
  (gl:clear-color 0.0 0.0 0.0 0.0)
  (gl:clear-depth 1.0)
  (gl:clear :color-buffer-bit :depth-buffer-bit)
  (gl:flush)
  (sdl:update-display))

(defun reshape (width height)
  (print width )
  (print height)
  (gl:viewport 0 0 width height))

(defmacro continuable (&body body)
  "Helper macro since we use continue restarts a lot
   <remember to hit C in slime or pick the restart so errors don't kill the app>"
  `(restart-case (progn ,@body)
     (continue () :report "Continue")))

(defun update-swank ()
  (let ((connection (or swank::*emacs-connection*
                        (swank::default-connection))))
    (when connection
      (swank::handle-requests connection t))))

(defun run-demo ()
  (sdl:with-init ()
    (sdl:window
     640 480 :opengl t
     :resizable t
     :opengl-attributes '((:sdl-gl-doublebuffer 1)
                          (:sdl-gl-alpha-size 0)
                          (:sdl-gl-depth-size 16)
                          (:sdl-gl-stencil-size 8)
                          (:sdl-gl-red-size 8)
                          (:sdl-gl-green-size 8)
                          (:sdl-gl-blue-size 8)))
    (init)
    (reshape 640 480)
    (setf cl-opengl-bindings:*gl-get-proc-address* #'sdl-cffi::sdl-gl-get-proc-address)
    (sdl:with-events ()
      (:quit-event () t)
      (:VIDEO-RESIZE-EVENT (:w width :h height)
                           (reshape width height))
      (:idle ()
             (continuable (update-swank))
             (continuable (draw))))))

好的,就是这样,玩得开心!

关于opengl - 我现在已经为 Glut Window 渲染了一个球体,如何让它随键盘移动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16133462/

相关文章:

C++ OpenGL 不渲染

c++ - 简单的彩色 3D 棱镜

emacs - 自定义组织模式导出

emacs - 有提示的查找文件?

lisp - 如何停止跟踪 lisp 中的函数?

opengl - 如何在OpenGL中导入对象以及选择什么文件格式?

c++ - 将 png 作为纹理加载并将其绑定(bind)到球体

emacs - 对齐来自emacs lisp的正则表达式

lisp - 使用 Lisp 计算阶乘

string - 在字符串中使用字符代码