3

在获取模型视图矩阵方面,glGetFloatv 似乎遇到了一些意想不到的麻烦(这也发生在尝试获取投影矩阵时)。

怎么了?好吧,不管矩阵实际上是什么,该函数都会返回单位矩阵,即使在平移和旋转之后也是如此!我知道这两个矩阵都不是单位矩阵,因为在游戏世界中移动时屏幕上的视觉效果完全符合预期。

我的功能是一点点 Common Lisp 代码(修改为在立即更改矩阵后打印矩阵以进行调试),并在下面进一步说明:

(defun apply-camera-gl (camera)
  (declare (type scene-camera camera))
  (declare (optimize (speed 3) (safety 1) (debug 3) (space 0)))
  "Passes the necessary OpenGL commands to apply the position and fov for the camera."
  (let ((pos (scene-camera-position camera))
        (rot (scene-camera-rot camera))
        (fov (scene-camera-fov camera)))
    (declare (type single-float rot fov)
             (type vec3 pos))

    (gl:matrix-mode :projection)
    (gl:load-identity)
    (set-perspective fov +sr+ 0.1 24.0)

    (gl:matrix-mode :modelview)
    (gl:load-identity)

    (gl:rotate -90.0 1.0 0.0 0.0)
    (gl:rotate rot 0.0 0.0 1.0)
    (gl:translate (- (the single-float (vec3-x pos)))
                  (- (the single-float (vec3-y pos)))
                  (- (the single-float (vec3-z pos))))

    ;; this always returns the following:
    ;; mv = #(1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0)
    (format t "mv = ~a~%" (gl:get-float :modelview-matrix))

    nil))

一些附加说明:

  • 我也尝试过,只是想看看会发生什么,将 (gl:get-float :modelview-matrix) 的打印输出更早地放在我的代码中的另一个文件的其他位置,实际上是在创建 OpenGL 上下文之后,我在其中应用一些随机的旋转和翻译调用——在那里它工作得很好,返回了我期望的矩阵!然而,在其他任何地方,它都会返回单位矩阵。我使用这个函数作为例子是因为它最容易理解,即使对于可能不熟悉 Lisp 的读者也是如此。
  • 我只能在 2001 年初的某个时候在 OpenGL 论坛上通过 Google 搜索其他人在 Internet 上找到一个实例。不幸的是,该线程以我的编程理智的祸根结束 - “哈哈,没关系,我找到了"的结论。
  • 我没有使用固定管道,但即使现代 OpenGL 最佳实践建议“在执行可编程管道时使用自己的矩阵”,我从未读过任何关于 OpenGL 禁用或以某种方式削弱与 OpenGL 相关的矩阵操作功能的某些部分的内容使用可编程流水线时拥有自己的矩阵。但是,为了确定起见,我还尝试了包装在一些代码中的 get-float 调用,它暂时禁用了可编程管道,并且在固定管道模式下它仍然返回单位矩阵。
  • 为了确保这不是 nvidia OpenGL 驱动程序中的一些奇怪的错误,我设法在使用英特尔图形驱动程序的笔记本电脑上重现了这个奇怪的异常。结果相同。
  • %gl:get-float-v 也会发生这种情况,它将输出转储到预先分配的外部数组中,而不是像 gl:get-float 那样返回 Lisp 数组。
  • 另外,在上面的代码中,我之前在 translate+rotate 调用之后和 get-float 调用之前尝试了 gl:finish (glFinish) 和 gl:flush (glFlush),基于某种模糊的怀疑,也许,只是也许,有些东西是发生故障。但是这些添加没有效果。
4

2 回答 2

2

我找到了它,实际上我很尴尬,我发布了这个巨大的文字墙问题,关于什么相当于我的一个非常愚蠢的疏忽。但也许像我一样大声说出这个问题,最终帮助我的大脑在睡了一夜之后理清第二天早上该做什么。

那么发生了什么:它返回了单位矩阵,因为我忘记了,几个月前,我在另一个文件中的代码的其他地方更广泛地调用了 apply-camera-gl 函数,在该文件中,它正在构建一个显示列表,旋转和平移作为显示列表本身的一部分(如果这对任何人来说听起来很奇怪,游戏是一个逐步移动的游戏,不像飞行模拟或 FPS)。

在显示列表构造块中,OpenGL 命令不会立即执行。

我重新安排了另一个文件中的代码,只在任何显示列表构造外壳之外调用 apply-camera-gl ......现在它得到了预期的矩阵,因为翻译和旋转被立即调用而不是被推迟到任何时候( gl:call-list ...) 发生。从现在开始,我将专门为几何使用显示列表——或者更好的是,完全停止使用它们并使用 VBO 来处理几何。

这也解释了为什么它在我把它放在 apply-camera-gl 之外的项目的其他地方返回单位矩阵——它们都恰好在显示列表构造块下,我昨晚甚至没有​​有意识地注意到(道德故事:“隧道视觉”是真实的)

我很抱歉,这个问题可能可以关闭。

于 2013-01-10T17:21:17.050 回答
0

嗯,我无法重现该问题,但我会展示我所做的,以便您看到。我正在使用 sbcl、quicklisp(获取 cl-opengl)并运行以下命令

CL-USER> (ql:quickload :cl-opengl)
To load "cl-opengl":
   Load 1 ASDF system:
     cl-opengl
; Loading "cl-opengl"
....
(:CL-OPENGL)
CL-USER> (ql:quickload :cl-glut)
 To load "cl-glut":
  Load 1 ASDF system:
    cl-glut
; Loading "cl-glut"
(:CL-GLUT)
CL-USER> (defclass smooth-window (glut:window)
            ()
            (:default-initargs :width 500 :height 500 :pos-x 100 :pos-y 100
                               :mode '(:single :rgb) :title "smooth.lisp"))
#<STANDARD-CLASS SMOOTH-WINDOW>

CL-USER> (defmethod glut:idle ((w smooth-window)) 
           (sleep 2)
           (gl:matrix-mode :modelview)
           (format t "~%~%(~{~5,3f~^ ~})" (coerce (gl:get-float :modelview-matrix) 'list))
           (gl:rotate 10 1.0 0.0 0.0)
           (format t "~%~%(~{~5,3f~^ ~})" (coerce (gl:get-float :modelview-matrix) 'list)))
STYLE-WARNING:
   redefining CL-GLUT:IDLE (#<STANDARD-CLASS SMOOTH-WINDOW>) in DEFMETHOD
#<STANDARD-METHOD CL-GLUT:IDLE (SMOOTH-WINDOW) {1005CB9363}>
CL-USER> (glut:display-window (make-instance 'smooth-window))


(1.000 0.000 0.000 0.000 0.000 1.000 0.000 0.000 0.000 0.000 1.000 0.000 0.000 0.000 0.000 1.000)

(1.000 0.000 0.000 0.000 0.000 0.985 0.174 0.000 0.000 -.174 0.985 0.000 0.000 0.000 0.000 1.000)

(1.000 0.000 0.000 0.000 0.000 0.985 0.174 0.000 0.000 -.174 0.985 0.000 0.000 0.000 0.000 1.000)

(1.000 0.000 0.000 0.000 0.000 0.940 0.342 0.000 0.000 -.342 0.940 0.000 0.000 0.000 0.000 1.000)

(1.000 0.000 0.000 0.000 0.000 0.940 0.342 0.000 0.000 -.342 0.940 0.000 0.000 0.000 0.000 1.000)

(1.000 0.000 0.000 0.000 0.000 0.866 0.500 0.000 0.000 -.500 0.866 0.000 0.000 0.000 0.000 1.000)

(1.000 0.000 0.000 0.000 0.000 0.866 0.500 0.000 0.000 -.500 0.866 0.000 0.000 0.000 0.000 1.000)

(1.000 0.000 0.000 0.000 0.000 0.766 0.643 0.000 0.000 -.643 0.766 0.000 0.000 0.000 0.000 1.000)

(1.000 0.000 0.000 0.000 0.000 0.766 0.643 0.000 0.000 -.643 0.766 0.000 0.000 0.000 0.000 1.000)

(1.000 0.000 0.000 0.000 0.000 0.643 0.766 0.000 0.000 -.766 0.643 0.000 0.000 0.000 0.000 1.000)
; No value

如果这个简单的例子有效,那么 (gl:rotate rot 0.0 0.0 1.0) 肯定有问题...我有可能它正在撤消旋转,所以它可以恢复身份?

对不起,我不能更精确,希望其他人可以填补我错过的位。李斯平快乐!

于 2013-01-10T09:55:35.080 回答