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 検索で 1 つのインスタンスしか見つけることができませんでした。 」 みたいな結論。
  • 私は固定パイプラインを使用していませんが、最新の OpenGL のベスト プラクティスでは「プログラム可能なパイプラインを実行するときに独自のマトリックスを使用する」ことが推奨されていますが、OpenGL を無効にしたり、OpenGL に関してマトリックス操作機能の一部を無効にしたりすることについては、何も読んだことがありません。プログラマブル パイプラインが使用される場合の独自の行列。ただし、念のため、プログラマブル パイプラインを一時的に無効にするコード内にラップされた get-float 呼び出しも試しましたが、固定パイプライン モードの場合でも恒等行列が返されました。
  • これが nvidia OpenGL ドライバーの奇妙なバグではないことを確認するために、Intel グラフィックス ドライバーを使用するラップトップでこの奇妙な異常を再現することができました。同じ結果です。
  • これは、gl:get-float のように Lisp 配列を返す代わりに、事前に割り当てられた外部配列に出力をダンプする %gl:get-float-v でも発生します。
  • また、上記のコードでは、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 に答える