Reputation:
I seem to be having some unexpected trouble with glGetFloatv with regards to fetching the modelview matrix (this also happens with trying to nab the projection matrix as well).
What happens? Well, regardless of what the matrix actually is, the function returns the identity matrix, even immediately after translation and rotations! I know neither matrix is the identity matrix, because the on-screen visuals are exactly as expected when moving around the game world.
My function is this little bit of Common Lisp code (modified with a statement to print the matrix after it's immediately changed for debugging purposes), and further notes below that:
(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))
Some additional notes:
Upvotes: 3
Views: 1902
Reputation:
I found it, and I'm actually embarrassed that I posted this big wall-of-text question about what amounts to a very stupid oversight on my part. But perhaps articulating the question out loud into words, as I did, finally helped my brain sort out what to do next the following morning after a night's sleep.
So what was happening: It was returning the identity matrix because I had forgotten I had, many months ago, called the apply-camera-gl function within a much wider enclosure elsewhere in my code in another file in which it was constructing a display list, with the rotations and translations as part of the display list itself (in case that sounds weird to anyone, the game is a game with step-wise movement, unlike a flight sim or FPS).
Within the display list construction block, OpenGL commands aren't immediately executed.
I re-arranged the code in the other file to just call apply-camera-gl outside of any display list construction enclosure... and now it gets the expected matrix because the translations and rotations get called immediately instead of being deferred until whenever (gl:call-list ...) happens. From now on I'll use display lists exclusively for geometry -- or better yet, cease using them entirely and use VBOs for geometry.
This also explains why it returned the identity matrix in other places in the project I put it in other than apply-camera-gl -- they all happened to be under display list construction blocks that I hadn't even consciously noticed last night (moral of the story: "tunnel vision" is a real thing)
My apologies, this question can probably be closed.
Upvotes: 2
Reputation: 3231
Hmmm, I'm unable to reproduce the issue but I will show what I did so you can see. I am using sbcl, quicklisp(to get cl-opengl) and ran the following
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
If this simple example works then there must be something up with the (gl:rotate rot 0.0 0.0 1.0)... I there any chance that it's undoing the rotation so it goes back to identity?
Sorry I couldn't be more precise, hopefully someone else can fill in the bits I missed. Happy Lisping!
Upvotes: 0