jak-project/goal_src/jak1/engine/gfx/math-camera.gc
ManDude 572e63f4a9
opengl: better handling of the draw region setting (#2746)
This fixes screenshots and a bunch of weird scissoring bugs. Fixes #2630
and fixes #2631
2023-06-19 04:15:33 +01:00

709 lines
26 KiB
Common Lisp

;;-*-Lisp-*-
(in-package goal)
;; name: math-camera.gc
;; name in dgo: math-camera
;; dgos: GAME, ENGINE
;;;;;;;;;;;;;;;;;;;;;;
;; math camera basics
;;;;;;;;;;;;;;;;;;;;;;
;; the math camera computes the perspective matrix, hvdf offset, and hmge scale.
;; multiplying a point by the perspective matrix, doing the persepctive divide, then adding hvdf offset gives you:
;; H : horizontal position (in GS coordinates)
;; V : vertical position (in GS coordinates)
;; D : depth (as a 24-bit integer for the z buffer)
;; F : fog
;; Multiplying by hmge then checking the clipping flags can be used to see if a point is outside the view frustum.
;; The "camera-temp" matrix is the perspective matrix multplied by the camera tranformation and is used
;; renderers that want a single matrix.
;;;;;;;;;;;;;;;;;;;
;; fog correction
;;;;;;;;;;;;;;;;;;;
;; The math-camera matrices are used to compute fogging values, which are a per-vertex uint8 that
;; tells the GS how "foggy" the color should be. This should be proportional to how far away the vertex
;; is. There is a scaling factor applied so the fog intensity isn't affected by the field of view angle.
;; The fog-corrector stores a fog-end fog-start value that is corrected for the field of view.
;; the actual correction factor is computed in cam-update.gc
(deftype fog-corrector (structure)
((fog-end float :offset-assert 0)
(fog-start float :offset-assert 4)
)
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
(defun fog-corrector-setup ((corrector fog-corrector) (math-cam math-camera))
"Set the fog corrector based on the supplied math-camera"
(set! (-> corrector fog-end) (* (-> math-cam fog-end) (-> math-cam fov-correction-factor)))
(set! (-> corrector fog-start) (* (-> math-cam fog-start) (-> math-cam fov-correction-factor)))
(none)
)
(define *math-camera-fog-correction* (new 'global 'fog-corrector))
(define-extern sprite-distorter-generate-tables (function none))
(defun update-math-camera ((math-cam math-camera) (video-mode symbol) (aspect symbol))
"Compute some one-time camera constants. These should only change when changing aspect ratio."
;; the x/y ratio are frustum slopes
(set! (-> math-cam x-ratio) (tan (* 0.5 (-> math-cam fov))))
(if (= aspect 'aspect4x3)
(set! (-> math-cam y-ratio) (* (1/ ASPECT_4X3) (-> math-cam x-ratio)))
(set! (-> math-cam y-ratio) (* (1/ ASPECT_16X9) (-> math-cam x-ratio)))
)
(with-pc
(cond
((-> *pc-settings* use-vis?)
;; using game vis, cannot allow seeing more of the view
;; crops excess aspect ratio at the top and bottom
;(set! (-> math-cam y-ratio) (* (1/ (-> *pc-settings* aspect-ratio)) (-> math-cam x-ratio)))
)
((real-movie?)
;; force the original 16x9 cropping during cutscenes.
(if (<= (-> *pc-settings* aspect-ratio) ASPECT_16X9)
(set! (-> math-cam y-ratio) (* (1/ (-> *pc-settings* aspect-ratio)) (-> math-cam x-ratio)))
(begin
(set! (-> math-cam y-ratio) (* (1/ ASPECT_16X9) (-> math-cam x-ratio)))
(*! (-> math-cam x-ratio) (/ (-> *pc-settings* aspect-ratio) ASPECT_16X9))
)
)
)
(else
;; not using game vis, allow *extended* aspect ratios
;; there is no vertical cropping, and you can see more of the sides
(set! (-> math-cam y-ratio) (* (1/ ASPECT_4X3) (-> math-cam x-ratio))) ;; same cropping as 4x3
(*! (-> math-cam x-ratio) (/ (-> *pc-settings* aspect-ratio) ASPECT_4X3)) ;; extend fov! shows more on the sides.
)
)
)
;; compute some culling constants. Not sure what these mean yet
(let ((x-rat (-> math-cam x-ratio))
(y-rat (-> math-cam y-ratio))
(cull-info (-> math-cam cull-info))
)
(let ((unused-x-thing (/ (+ 1.0 (* 4.0 x-rat x-rat)) (+ 1.0 (* x-rat x-rat))))))
(let ((y-thing (/ (+ 1.0 (* (* 4.0 y-rat) y-rat)) (+ 1.0 (* y-rat y-rat)))))
(set! (-> cull-info x-fact) (/ (+ 1.0 (* 4.0 x-rat x-rat)) (* x-rat (sqrtf (+ 1.0 (* 16.0 x-rat x-rat))))))
(set! (-> cull-info y-fact) (/ (+ 1.0 (* 4.0 y-rat y-rat)) (* y-rat (sqrtf (+ 1.0 (* 16.0 y-rat y-rat))))))
(set! (-> cull-info z-fact) (sqrtf (+ (* (+ -4.0 y-thing) (+ -4.0 y-thing) y-rat y-rat) (* (+ -1.0 y-thing) (+ -1.0 y-thing)))))
)
;; radius of sphere containing camera origin and intersection of near plane and frustum
(let* ((near-x (* x-rat (-> math-cam d)))
(near-y (* y-rat (-> math-cam d)))
(near-corner-dist-sqr (+ (* near-x near-x) (* near-y near-y)))
(near-z (-> math-cam d))
)
(set! (-> cull-info cam-radius) (sqrtf (+ near-corner-dist-sqr (* near-z near-z))))
)
;; frustum plane equations coefficients?
(let* ((dx-rat-2 (* (-> math-cam d) (-> math-cam x-ratio)))
(d-temp-2 (-> math-cam d))
(dx-rat-times-4 (* 4.0 dx-rat-2))
(d-temp-3 (-> math-cam d))
)
(let ((inverse-x-len (/ 1.0 (sqrtf (+ (* dx-rat-2 dx-rat-2) (* d-temp-2 d-temp-2)))))
(inverse-x-len-2 (/ 1.0 (sqrtf (+ (* dx-rat-times-4 dx-rat-times-4) (* d-temp-3 d-temp-3)))))
)
(set! (-> cull-info xz-dir-ax) (* dx-rat-2 inverse-x-len))
(set! (-> cull-info xz-dir-az) (* d-temp-2 inverse-x-len))
(set! (-> cull-info xz-dir-bx) (* dx-rat-times-4 inverse-x-len-2))
(set! (-> cull-info xz-dir-bz) (* d-temp-3 inverse-x-len-2))
)
(set!
(-> cull-info xz-cross-ab)
(- (* dx-rat-2 d-temp-3) (* d-temp-2 dx-rat-times-4))
)
)
(let* ((dy-rat (* (-> math-cam d) (-> math-cam y-ratio)))
(d-temp-4 (-> math-cam d))
(dy-rat-times-4 (* 4.0 dy-rat))
(d-temp-5 (-> math-cam d))
)
(let ((inverse-y-len (/ 1.0 (sqrtf (+ (* dy-rat dy-rat) (* d-temp-4 d-temp-4)))))
(inverse-y-len-2 (/ 1.0 (sqrtf (+ (* dy-rat-times-4 dy-rat-times-4) (* d-temp-5 d-temp-5)))))
)
(set! (-> cull-info yz-dir-ay) (* dy-rat inverse-y-len))
(set! (-> cull-info yz-dir-az) (* d-temp-4 inverse-y-len))
(set! (-> cull-info yz-dir-by) (* dy-rat-times-4 inverse-y-len-2))
(set! (-> cull-info yz-dir-bz) (* d-temp-5 inverse-y-len-2))
)
(set!
(-> cull-info yz-cross-ab)
(- (* dy-rat d-temp-5) (* d-temp-4 dy-rat-times-4))
)
)
)
;; fog setup
(fog-corrector-setup *math-camera-fog-correction* math-cam)
;; reset camera rotation
(matrix-identity! (-> math-cam camera-rot))
;;;;;;;;;;;;;; Perspective matrix setup
;; these min/max depths are the values we'd want to write to the 24-bit integer depth buffer
(let ((min-depth 100.0)
(max-depth 16760631.0) ;; almost 2^24.
)
(let ((f0-21 16777115.0))) ;; unused. this is actually float closest to 2^24
;; next, compute the fog slope d(8bit_integer_fog_value)/d(game_world_distance).
;; the final fog values we want are an 8-bit integer.
;; note that this is the fog at the near plane too.
(let ((fog-slope
(/ (* (-> math-cam d) (- (-> math-cam fog-min) (-> math-cam fog-max)))
(- (-> *math-camera-fog-correction* fog-end)
(-> *math-camera-fog-correction* fog-start)
)
)
)
;; this is half the range of the depth buffer.
(depth-buffer-half-range (* -0.5 (- max-depth min-depth)))
)
;; this is the slope to convert game world depths to depth buffer depths
(let ((half-depth-buffer-slope (/ depth-buffer-half-range (* (-> math-cam d) (- (-> math-cam f) (-> math-cam d)))))
(cam-fov-mult (-> math-cam fov-correction-factor))
)
;; finally, build the actual matrix.
;; x/y are just the usual scaling
(set! (-> math-cam perspective vector 0 x) (* cam-fov-mult (- (/ (-> math-cam x-pix) (* (-> math-cam x-ratio) (-> math-cam d))))))
(set! (-> math-cam perspective vector 1 y) (* cam-fov-mult (- (/ (-> math-cam y-pix) (* (-> math-cam y-ratio) (-> math-cam d))))))
;; depth scaling
(set! (-> math-cam perspective vector 2 z) (* cam-fov-mult (+ (-> math-cam f) (-> math-cam d)) half-depth-buffer-slope))
;; depth to fog
(set! (-> math-cam perspective vector 2 w) (* (/ cam-fov-mult (-> math-cam d)) fog-slope))
(set! (-> math-cam perspective vector 3 z) (* -2.0 half-depth-buffer-slope (-> math-cam f) (-> math-cam d) cam-fov-mult))
)
;; hvdf = horizontal, vertical, depth, fog offsets to be applied after transform.
(let ((hvdf-x 2048.0)
(hvdf-y 2048.0)
(hvdf-w
(/ (- (* (-> *math-camera-fog-correction* fog-end) (-> math-cam fog-max))
(* (-> *math-camera-fog-correction* fog-start)
(-> math-cam fog-min)
)
)
(- (-> *math-camera-fog-correction* fog-end)
(-> *math-camera-fog-correction* fog-start)
)
)
)
)
(let ((hvdf-z (* 0.5 (+ max-depth min-depth))))
(set! (-> math-cam hmge-scale x) (/ 1.0 (-> math-cam x-clip)))
(set! (-> math-cam hmge-scale y) (/ 1.0 (-> math-cam y-clip)))
(set! (-> math-cam hmge-scale z) (/ 1.0 depth-buffer-half-range))
(set! (-> math-cam hmge-scale w) (/ 1.0 fog-slope))
(set! (-> math-cam inv-hmge-scale x) (-> math-cam x-clip))
(set! (-> math-cam inv-hmge-scale y) (-> math-cam y-clip))
(set! (-> math-cam inv-hmge-scale z) depth-buffer-half-range)
(set! (-> math-cam inv-hmge-scale w) fog-slope)
(set! (-> math-cam hvdf-off x) hvdf-x)
(set! (-> math-cam hvdf-off y) hvdf-y)
(set! (-> math-cam hvdf-off z) hvdf-z)
(set! (-> math-cam hvdf-off w) hvdf-w)
(set! (-> math-cam guard x) (/ (-> math-cam x-clip) (-> math-cam x-pix)))
(set! (-> math-cam guard y) (/ (-> math-cam y-clip) (-> math-cam y-pix)))
(set! (-> math-cam guard z) 1.0)
(set! (-> math-cam guard w) 1.0)
(set! (-> math-cam isometric vector 3 z) (- 16777215.0 hvdf-z))
;; PC HACK!
;; for whatever reason, the font renderer ends up computing a depth #x1000000 instead of
;; #xffffffff, which overflows the 24-bit z buffer.
;; cheating this by 1 bit seems to fix it.
(#when PC_PORT
;; #x4b002032 -> #x4b002031
(set! (-> math-cam isometric vector 3 z) (the-as float (1- (the-as int (-> math-cam isometric vector 3 z)))))
;; also do mirror game check here.
(when (pc-cheats? (-> *pc-settings* cheats) mirror)
(*! (-> math-cam perspective vector 0 x) -1.)
)
)
)
(set! (-> math-cam isometric vector 3 w) fog-slope)
;; perspective matrix
(let ((persp-xx (-> math-cam perspective vector 0 x))
(persp-yy (-> math-cam perspective vector 1 y))
(persp-x (* -1.9996 (-> math-cam perspective vector 0 x)))
)
(let ((sprite-row-0 (-> math-cam sprite-2d)))
(set! (-> sprite-row-0 vector 0 x) persp-x)
(set! (-> sprite-row-0 vector 0 y) 0.0)
(set! (-> sprite-row-0 vector 0 z) 0.0)
(set! (-> sprite-row-0 vector 0 w) 0.0)
)
(set-vector! (-> math-cam sprite-2d vector 1) 0.0 (- (* (/ persp-yy persp-xx) persp-x)) 0.0 0.0)
(set-vector! (-> math-cam sprite-2d vector 2) 0.0 0.0 (- persp-x) 0.0)
(set-vector!
(-> math-cam sprite-2d vector 3)
0.0
0.0
(* 500000000.0 persp-x)
(* 60.0 persp-x (-> math-cam pfog0))
)
)
(set! (-> math-cam sprite-2d-hvdf quad) (-> math-cam hvdf-off quad))
(set! (-> math-cam sprite-2d-hvdf x) 2048.0)
(set! (-> math-cam sprite-2d-hvdf y) 2048.0)
(set! (-> math-cam sprite-2d-hvdf z) (-> math-cam hvdf-off z))
(set! (-> math-cam pfog0) fog-slope)
(set! (-> math-cam pfog1) hvdf-w)
)
)
)
;; sets up some giftags, but they are totally wrong.
;; they use 32-bit variables to store 64-bit parts of the tag.
(let ((v1-17 0)))
(let ((v1-20 (make-u128 0 (shl #x301ec000 32)))))
(let ((v1-23 (make-u128 0 (shl #x303ec000 32)))))
(let ((pfog (-> math-cam pfog0)))
(let ((vis-gif-0 (-> math-cam vis-gifs)))
(set! (-> vis-gif-0 0 fog0) (the-as uint pfog))
(set! (-> vis-gif-0 0 strip) (the-as uint #x301e4000))
(set! (-> vis-gif-0 0 regs) (the-as uint 1042))
(set! (-> vis-gif-0 0 fan) (the-as uint #x301ec000))
)
(let ((vis-gif-1 (&-> math-cam gifgr)))
(set! (-> vis-gif-1 0) (the-as vis-gif-tag pfog))
(set!
(-> vis-gif-1 1)
(the-as vis-gif-tag (make-u128 0 (shl #x20164000 32)))
)
(set! (-> vis-gif-1 2) (the-as vis-gif-tag 65))
(set! (-> vis-gif-1 3) (the-as vis-gif-tag #x301ec000))
)
(let ((vis-gif-1-again (-> math-cam vis-gifs)))
(set! (-> vis-gif-1-again 0 fog0) (the-as uint pfog))
(set! (-> vis-gif-1-again 0 strip) (the-as uint #x303e4000))
(set! (-> vis-gif-1-again 0 regs) (the-as uint 1042))
(set! (-> vis-gif-1-again 0 fan) (the-as uint #x303ec000))
)
(let ((vis-gif-1-again-again (-> math-cam vis-gifs)))
(set! (-> vis-gif-1-again-again 0 fog0) (the-as uint pfog))
(set! (-> vis-gif-1-again-again 0 strip) (the-as uint #x303e4000))
(set! (-> vis-gif-1-again-again 0 regs) (the-as uint 1042))
(set! (-> vis-gif-1-again-again 0 fan) (the-as uint #x303ec000))
)
)
;; update sprite stuff.
(if (nonzero? sprite-distorter-generate-tables)
(sprite-distorter-generate-tables)
)
math-cam
)
(defmethod new math-camera ((allocation symbol) (type-to-make type))
"Set up a new math-camera in NTSC mode."
(let ((gp-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
(set! (-> gp-0 d) 1024.0)
(set! (-> gp-0 f) 40960000.0)
(set! (-> gp-0 fov) 11650.845)
(set! (-> gp-0 x-pix) 256.0)
(set! (-> gp-0 x-clip) 1024.0)
(set! (-> gp-0 y-pix) 112.0)
(set! (-> gp-0 y-clip) 448.0)
(set! (-> gp-0 fog-start) 40960.0)
(set! (-> gp-0 fog-end) 819200.0)
(set! (-> gp-0 fog-max) 255.0)
(set! (-> gp-0 fog-min) 150.0)
(matrix-identity! (-> gp-0 inv-camera-rot))
(matrix-identity! (-> gp-0 camera-rot))
(vector-reset! (-> gp-0 trans))
(set! (-> gp-0 isometric vector 0 x) 1.0)
(set! (-> gp-0 isometric vector 1 y) 0.5)
(set! (-> gp-0 isometric vector 2 z) -1.0)
(set! (-> gp-0 reset) 1)
(set! (-> gp-0 smooth-step) 0.0)
(set! (-> gp-0 smooth-t) 0.0)
(update-math-camera gp-0 'ntsc 'aspect4x3)
)
)
(define *math-camera* (new 'global 'math-camera))
(defun math-cam-start-smoothing ((arg0 float) (arg1 float))
"Unused camera smoothing"
(set! (-> *math-camera* smooth-step) (/ 1.0 arg0))
(set! (-> *math-camera* smooth-t) arg1)
(matrix->quaternion (-> *math-camera* inv-camera-rot-smooth-from) (-> *math-camera* inv-camera-rot-smooth))
)
(defun move-target-from-pad ((trans transform) (pad-idx int))
"Unused function to adjust trans based on inputs from the pad.
This function must be extremely old because it takes a non-quaternion transform,
and all target stuff uses quaternions."
;; local-trans is the translation in the camera frame.
(let ((local-trans (new-stack-vector0)))
;; circle/square move camera relative x (left and right)
(set! (-> local-trans x)
(cond
((logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons circle))
-80.0
)
((logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons square))
80.0
)
(else
0.0
)
)
)
;; no way to move camera relative y (up/down)
(set! (-> local-trans y) 0.0)
;; in and out movement
(set! (-> local-trans z)
(cond
((logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons down))
-80.0
)
((logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons up))
80.0
)
(else
0.0
)
)
)
(set! (-> local-trans w) 1.0)
;; rotate this into world frame
(let ((inv-cam-rot (new-stack-vector0))
(cam-rot-mat (new-stack-matrix0)))
;; unused.
(vector-negate! inv-cam-rot (-> trans rot))
;; convert rotation to rotation matrix.
(matrix-rotate-zyx! cam-rot-mat (-> trans rot))
;; and rotate the translation.
(vector-matrix*! local-trans local-trans cam-rot-mat)
)
;; and update the transform
(vector+! (-> trans trans) (-> trans trans) local-trans)
)
;; don't forget to fix w.
(set! (-> trans trans w) 1.0)
;; global translation
(if (logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons r1))
(set! (-> trans trans y) (+ 80.0 (-> trans trans y)))
)
(if (logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons r2))
(set! (-> trans trans y) (+ -80.0 (-> trans trans y)))
)
;; rotation (don't allow camera roll)
(if (logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons x))
(set! (-> trans rot x) (+ 546.13336 (-> trans rot x)))
)
(if (logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons triangle))
(set! (-> trans rot x) (+ -546.13336 (-> trans rot x)))
)
(if (logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons left))
(set! (-> trans rot y) (+ 546.13336 (-> trans rot y)))
)
(if (logtest? (-> *cpad-list* cpads pad-idx button0-abs 0) (pad-buttons right))
(set! (-> trans rot y) (+ -546.13336 (-> trans rot y)))
)
trans
)
(defun transform-point-vector! ((arg0 vector) (arg1 vector))
"Apply camera transformation to a point. Return true if it is visible or not.
This returns the point in GS coords, but as float instead of int, so it's
not really useful. See transform-point-qword! for more details"
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf23 :class vf)
(vf24 :class vf)
(vf25 :class vf)
(vf26 :class vf)
(vf27 :class vf)
(vf28 :class vf)
(vf29 :class vf)
(vf30 :class vf)
(vf31 :class vf)
)
(init-vf0-vector)
(let ((v1-0 0))
)
(.lvf vf24 (&-> *math-camera* camera-temp vector 0 quad))
(.lvf vf25 (&-> *math-camera* camera-temp vector 1 quad))
(.lvf vf26 (&-> *math-camera* camera-temp vector 2 quad))
(.lvf vf27 (&-> *math-camera* camera-temp vector 3 quad))
(.lvf vf29 (&-> *math-camera* hmge-scale quad))
(.lvf vf30 (&-> *math-camera* hvdf-off quad))
(.lvf vf28 (&-> arg1 quad))
(.mul.x.vf acc vf24 vf28)
(.add.mul.y.vf acc vf25 vf28 acc)
(.add.mul.z.vf acc vf26 vf28 acc)
(.add.mul.w.vf vf28 vf27 vf0 acc)
(.add.w.vf vf23 vf0 vf0)
(.mul.vf vf31 vf28 vf29)
;;(TODO.VCLIP vf31 vf31)
(let ((clip (vu-clip vf31 0)))
(.div.vf Q vf0 vf31 :fsf #b11 :ftf #b11)
(.wait.vf)
;;(.cfc2.i v1-7 Clipping)
(.mul.vf vf28 vf28 Q :mask #b111)
(.mul.vf vf23 vf23 Q)
(.add.vf vf28 vf28 vf30)
(.max.x.vf vf28 vf28 vf0 :mask #b1000)
(.svf (&-> arg0 quad) vf28)
(zero? (logand clip 63))
)
)
)
(defun transform-point-qword! ((arg0 vector4w) (arg1 vector))
"Apply camera transformation to point, returning fixed point 28.4 position
that can be given to the GS directly."
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf23 :class vf)
(vf24 :class vf)
(vf25 :class vf)
(vf26 :class vf)
(vf27 :class vf)
(vf28 :class vf)
(vf29 :class vf)
(vf30 :class vf)
(vf31 :class vf)
)
(init-vf0-vector)
(let ((v1-0 0))
)
;; this camera matrix has both the projection and camera translation/rotation
(.lvf vf24 (&-> *math-camera* camera-temp vector 0 quad))
(.lvf vf25 (&-> *math-camera* camera-temp vector 1 quad))
(.lvf vf26 (&-> *math-camera* camera-temp vector 2 quad))
(.lvf vf27 (&-> *math-camera* camera-temp vector 3 quad))
;; scaling
(.lvf vf29 (&-> *math-camera* hmge-scale quad))
;; offset
(.lvf vf30 (&-> *math-camera* hvdf-off quad))
;; input point
(.lvf vf28 (&-> arg1 quad))
;; matrix multiply, result in vf28
(.mul.x.vf acc vf24 vf28)
(.add.mul.y.vf acc vf25 vf28 acc)
(.add.mul.z.vf acc vf26 vf28 acc)
(.add.mul.w.vf vf28 vf27 vf0 acc)
(.add.w.vf vf23 vf0 vf0) ;; set w = 1.0
;; apply hmge scaling. the result of this multiply sets clipping flags appropriately
(.mul.vf vf31 vf28 vf29) ;; scale.
;;(TODO.VCLIP vf31 vf31)
(let ((clip (vu-clip vf31 0))) ;; clip!
;; perspective divide
(.div.vf Q vf0 vf31 :fsf #b11 :ftf #b11)
(.wait.vf)
;;(.cfc2.i v1-7 Clipping)
;; perspective
(.mul.vf vf28 vf28 Q :mask #b111)
;; compute scale factor (w was 1.0)
(.mul.vf vf23 vf23 Q)
;; apply hvdf offsets
(.add.vf vf28 vf28 vf30)
;; saturate fog
(.max.x.vf vf28 vf28 vf0 :mask #b1000)
;; convert to GS fixed point
(vftoi4.xyzw vf28 vf28)
;; store result!
(.svf (&-> arg0 quad) vf28)
;; return result of clipping.
(zero? (logand clip 63))
)
)
)
(defun transform-point-vector-scale! ((arg0 vector) (arg1 vector))
"Similar to transform-point-qword! but returns the scale factor instead."
(local-vars (v0-0 float))
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf23 :class vf)
(vf24 :class vf)
(vf25 :class vf)
(vf26 :class vf)
(vf27 :class vf)
(vf28 :class vf)
(vf29 :class vf)
(vf30 :class vf)
(vf31 :class vf)
)
(init-vf0-vector)
(let ((v1-0 0))
)
(.lvf vf24 (&-> *math-camera* camera-temp vector 0 quad))
(.lvf vf25 (&-> *math-camera* camera-temp vector 1 quad))
(.lvf vf26 (&-> *math-camera* camera-temp vector 2 quad))
(.lvf vf27 (&-> *math-camera* camera-temp vector 3 quad))
(.lvf vf29 (&-> *math-camera* hmge-scale quad))
(.lvf vf30 (&-> *math-camera* hvdf-off quad))
(.lvf vf28 (&-> arg1 quad))
(.mul.x.vf acc vf24 vf28)
(.add.mul.y.vf acc vf25 vf28 acc)
(.add.mul.z.vf acc vf26 vf28 acc)
(.add.mul.w.vf vf28 vf27 vf0 acc)
(.add.w.vf vf23 vf0 vf0)
(.mul.vf vf31 vf28 vf29)
;;(TODO.VCLIP vf31 vf31) clip result was unused
(.div.vf Q vf0 vf31 :fsf #b11 :ftf #b11)
(.wait.vf)
;;(.cfc2.i v1-7 Clipping)
(.mul.vf vf28 vf28 Q :mask #b111)
(.mul.vf vf23 vf23 Q)
(.add.vf vf28 vf28 vf30)
(.max.x.vf vf28 vf28 vf0 :mask #b1000)
(.svf (&-> arg0 quad) vf28)
;;(let ((a0-2 (zero? (logand v1-7 63))))
;; )
(.mov v0-0 vf23)
v0-0
)
)
(defun init-for-transform ((arg0 matrix))
"Sets up VU0 registers with camera info.
This is probably a very old function and it's only used by jungle mirrors.
It stashes some data in vector float registers that must be there before calling transform-float-point."
(rlet ((vf1 :class vf)
(vf17 :class vf)
(vf18 :class vf)
(vf19 :class vf)
(vf2 :class vf)
(vf23 :class vf)
(vf24 :class vf)
(vf25 :class vf)
(vf26 :class vf)
(vf27 :class vf)
(vf28 :class vf)
(vf29 :class vf)
(vf3 :class vf)
(vf4 :class vf)
(vf6 :class vf)
(vf7 :class vf)
(vf8 :class vf)
(vf9 :class vf)
)
(let ((gp-0 (new-stack-matrix0))
(s5-0 (new-stack-matrix0))
(s4-0 (new 'stack 'vector4s-3))
(s3-0 (new-stack-vector0))
(s2-0 (new 'stack 'vector4s-3))
)
(matrix*! s5-0 arg0 (-> *math-camera* camera-temp))
(matrix-3x3-inverse-transpose! gp-0 arg0)
(let ((v1-3 s3-0))
(set! (-> v1-3 x) 0.4)
(set! (-> v1-3 y) 0.4)
(set! (-> v1-3 z) 0.4)
(set! (-> v1-3 w) 1.0)
)
(let ((v1-4 (-> s4-0 data)))
(set! (-> v1-4 0) 1.0)
(set! (-> v1-4 1) 1.0)
(set! (-> v1-4 2) 1.0)
(set! (-> v1-4 3) 1.0)
)
(let ((v1-5 (&-> s4-0 data 4)))
(set! (-> v1-5 0) 0.0)
(set! (-> v1-5 1) 0.0)
(set! (-> v1-5 2) 0.0)
(set! (-> v1-5 3) 1.0)
)
(let ((v1-6 (&-> s4-0 data 8)))
(set! (-> v1-6 0) 0.0)
(set! (-> v1-6 1) 0.0)
(set! (-> v1-6 2) 0.0)
(set! (-> v1-6 3) 1.0)
)
(let ((v1-7 (-> s2-0 data)))
(set! (-> v1-7 0) 1.0)
(set! (-> v1-7 1) 0.0)
(set! (-> v1-7 2) 0.0)
(set! (-> v1-7 3) 1.0)
)
(let ((v1-8 (&-> s2-0 data 4)))
(set! (-> v1-8 0) 0.0)
(set! (-> v1-8 1) 1.0)
(set! (-> v1-8 2) 0.0)
(set! (-> v1-8 3) 1.0)
)
(let ((v1-9 (&-> s2-0 data 8)))
(set! (-> v1-9 0) 0.0)
(set! (-> v1-9 1) 0.0)
(set! (-> v1-9 2) 1.0)
(set! (-> v1-9 3) 1.0)
)
(.lvf vf7 (&-> *math-camera* hmge-scale quad))
(.lvf vf8 (&-> *math-camera* hvdf-off quad))
(.lvf vf9 (&-> *math-camera* giftex))
(let ((v1-13 255))
(.mov vf6 v1-13)
)
;;(.mov v1-14 vf6)
(.itof.vf vf6 vf6)
(.svf (&-> *transform-regs* vf7) vf7)
(.svf (&-> *transform-regs* vf8) vf8)
(.svf (&-> *transform-regs* vf9) vf9)
(.svf (&-> *transform-regs* vf6) vf6)
(set! (-> *transform-regs* vf1) (-> s5-0 vector 0 quad))
(set! (-> *transform-regs* vf2) (-> s5-0 vector 1 quad))
(set! (-> *transform-regs* vf3) (-> s5-0 vector 2 quad))
(set! (-> *transform-regs* vf4) (-> s5-0 vector 3 quad))
(set! (-> *transform-regs* vf17) (-> gp-0 vector 0 quad))
(set! (-> *transform-regs* vf18) (-> gp-0 vector 1 quad))
(set! (-> *transform-regs* vf19) (-> gp-0 vector 2 quad))
(set! (-> *transform-regs* vf23) (-> s2-0 quad 0))
(set! (-> *transform-regs* vf24) (-> s2-0 quad 1))
(set! (-> *transform-regs* vf25) (-> s2-0 quad 2))
(set! (-> *transform-regs* vf27) (-> s4-0 quad 0))
(set! (-> *transform-regs* vf28) (-> s4-0 quad 1))
(set! (-> *transform-regs* vf29) (-> s4-0 quad 2))
(set! (-> *transform-regs* vf26) (-> s3-0 quad))
)
(none)
)
)