Files
jak-project/goal_src/engine/camera/math-camera.gc
T
ManDude 7cb04c6cd5 [decomp] font-h, fix a vector type, minor decompiler fixes (#411)
* Make `:do-not-decompile` work on field lookup as well

* decompile `font-h` and update a vector type + minor fixes

* fix some types

* fix font-h

* fix font-h (again)

* update a script

* fixes

* Fix segfault

* Fix `PROT_NONE` page protection on windows
2021-05-01 21:09:48 -04:00

410 lines
14 KiB
Common Lisp

;;-*-Lisp-*-
(in-package goal)
;; name: math-camera.gc
;; name in dgo: math-camera
;; dgos: GAME, ENGINE
(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 from the math camera"
;; just apply the correction factor to the value is math cam.
(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))
(local-vars
(cam-mat matrix)
(cull-info cull-info)
(sprite-row-0 matrix)
(sprite-row-1 (pointer float))
(sprite-row-2 (pointer float))
(sprite-row-3 (pointer float))
(v1-15 vector)
(v1-17 int)
(v1-19 int)
(v1-20 int)
(v1-22 int)
(v1-23 int)
(pfog float)
(a0-10 vector)
(a0-11 int)
(vis-gif-0 vis-gif-tag)
(vis-gif-1 vis-gif-tag)
(vis-gif-1-again vis-gif-tag)
(vis-gif-1-again-again vis-gif-tag)
(a1-5 int)
(a1-6 int)
(y-rat float)
(drat-sqr-len float)
(fog-contsant-3 float)
(d-temp-2 float)
(d-temp-4 float)
(fog-constant-3 float)
(fog-at-d float)
(x-rat float)
(dy-rat float)
(d-temp float)
(dx-rat-2 float)
;;(dy-rat float)
(mid-range float)
(persp-x float)
(temp7 float)
(unused-x-thing float)
(y-thing float)
(dx-rat float)
(dx-rat-times-4 float)
(dy-rat-times-4 float)
(very-near float)
(hvdf-z float)
(persp-xx float)
(d-temp-3 float)
(d-temp-5 float)
(very-far float)
(persp-yy float)
(inverse-x-len float)
(inverse-y-len float)
(cam-fov-mult float)
(hvdf-w float)
(inverse-x-len-2 float)
(inverse-y-len-2 float)
(range-factor float)
(hvdf-x float)
(hvdf-y float)
)
;; Camera Math:
;; The camera transformation projects a point in space to the camera's projection plane.
;; The usual camera frustum is shown below:
;;
;; * <- the camera origin.
;; --- <- project the point onto this plane, the screen.
;; / | \
;; / | \
;; / | * \ <- some point in the world
;; The "x ratio" is the slope of frustum:
;; for a point on the frustum (px,pz), it satisfies x_ratio * pz = px.
;; Compute the x-ratio using half of the fov angle (the triangle is the midplane, frustum wall, and offset in x)
(set! (-> math-cam x-ratio) (tan (* 0.500000 (-> math-cam fov))))
;; The plane has the same aspect ratio as the screen, so we can derive the y-ratio
;; based on the game's aspect ratio setting.
(if (= aspect 'aspect4x3)
(set! (-> math-cam y-ratio) (* 0.75 (-> math-cam x-ratio)))
(set! (-> math-cam y-ratio) (* 0.5625 (-> math-cam x-ratio)))
)
;; Eventually, we will want to cull things that are oustide of the view frustum.
;; To do this, we need to compute the equation of the planes for the sides of the frustum.
;; I'm not yet sure what these "x-fact" things are, but likely related to their culling strategy.
(set! x-rat (-> math-cam x-ratio))
(set! y-rat (-> math-cam y-ratio))
(set! cull-info (-> math-cam cull-info))
(set! unused-x-thing
(/ (+ 1.000000 (* (* 4.000000 x-rat) x-rat)) (+ 1.000000 (* x-rat x-rat)))
)
(set! y-thing
(/ (+ 1.000000 (* (* 4.000000 y-rat) y-rat)) (+ 1.000000 (* y-rat y-rat)))
)
(set!
(-> cull-info x-fact)
(/ (+ 1.000000 (* (* 4.000000 x-rat) x-rat))
(* x-rat (sqrtf (+ 1.000000 (* (* 16.000000 x-rat) x-rat))))
)
)
(set!
(-> cull-info y-fact)
(/ (+ 1.000000 (* (* 4.000000 y-rat) y-rat))
(* y-rat (sqrtf (+ 1.000000 (* (* 16.000000 y-rat) y-rat))))
)
)
(set! (-> cull-info z-fact)
(sqrtf (+ (* (* (* (+ -4.000000 y-thing) (+ -4.000000 y-thing)) y-rat) y-rat)
(* (+ -1.000000 y-thing) (+ -1.000000 y-thing))
)
)
)
;; this is the distance from the origin of the projection plane to the frustum, in x
(set! dx-rat (* x-rat (-> math-cam d)))
;; this is the distance from the origin of the projection plane to the frustum, in y
(set! dy-rat (* y-rat (-> math-cam d)))
;; this is the distance from the origin of the projection plane to the corner of the frustum
(set! drat-sqr-len (+ (* dx-rat dx-rat) (* dy-rat dy-rat)))
;; this is the distance from the origin (behind the projection plane)
;; to the farthest point of the intersection of the view frustum and the projection plane
(set! d-temp (-> math-cam d))
(set! (-> cull-info cam-radius) (sqrtf (+ drat-sqr-len (* d-temp d-temp))))
;; origin of projection plane to frustum, x
(set! dx-rat-2 (* (-> math-cam d) (-> math-cam x-ratio)))
(set! d-temp-2 (-> math-cam d))
;; ?? not sure what this is used for
(set! dx-rat-times-4 (* 4.000000 dx-rat-2))
(set! d-temp-3 (-> math-cam d))
;; 1/length(cam origin to frust x on projection plane)
(set! inverse-x-len
(/ 1.000000 (sqrtf (+ (* dx-rat-2 dx-rat-2) (* d-temp-2 d-temp-2))))
)
(set! inverse-x-len-2
(/ 1.000000
(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)) ;; frustum normal x (scaled)
(set! (-> cull-info xz-dir-az) (* d-temp-2 inverse-x-len)) ;; normal z (scaled)
;; not sure what this "b" means, but it just seems like it's a much wider frustum?
(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))
;; not sure why you'd want this, but okay.
(set! (-> cull-info xz-cross-ab) (- (* dx-rat-2 d-temp-3) (* d-temp-2 dx-rat-times-4)))
;; Repeat of the above math for y.
(set! dy-rat (* (-> math-cam d) (-> math-cam y-ratio)))
(set! d-temp-4 (-> math-cam d))
(set! dy-rat-times-4 (* 4.000000 dy-rat))
(set! d-temp-5 (-> math-cam d))
(set! inverse-y-len
(/ 1.000000 (sqrtf (+ (* dy-rat dy-rat) (* d-temp-4 d-temp-4))))
)
(set! inverse-y-len-2
(/ 1.000000
(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)))
;; update the fog corrector.
(fog-corrector-setup *math-camera-fog-correction* math-cam)
;; not sure why we do this here.
(set! cam-mat (matrix-identity! (-> math-cam camera-rot)))
(set! very-near 100.000000)
(set! very-far 16760631.000000) ;; this is ~4091.95 meters.
(set! fog-constant-3 16777115.000000) ;; unused.
;; this is actually fog.
(set! fog-at-d
(/ (* (-> math-cam d) (- (-> math-cam fog-min) (-> math-cam fog-max))) ;; fog of the plane
(- (-> *math-camera-fog-correction* fog-end) (-> *math-camera-fog-correction* fog-start)) ;; corrected fog.
)
)
(set! mid-range (* -0.500000 (- very-far very-near)))
;; not sure what this is doing exactly
(set! range-factor
(/ mid-range
(* (-> math-cam d) (- (-> math-cam f) (-> math-cam d)))
)
)
(set! cam-fov-mult (-> math-cam fov-correction-factor))
(set! (-> math-cam perspective data 0)
(* cam-fov-mult
(- (/ (-> math-cam x-pix) ;; scale for pixels I guess?
(* (-> math-cam x-ratio) (-> math-cam d)) ;; width of frustum
)
)
)
)
(set! (-> math-cam perspective data 5)
(* cam-fov-mult
(- (/ (-> math-cam y-pix) (* (-> math-cam y-ratio) (-> math-cam d))))
)
)
(set! (-> math-cam perspective data 10)
(* cam-fov-mult
(+ (-> math-cam f) (-> math-cam d))
range-factor
)
)
(set! (-> math-cam perspective data 11)
(* (/ cam-fov-mult (-> math-cam d)) fog-at-d)
)
(set! (-> math-cam perspective data 14)
(* -2.000000 range-factor (-> math-cam f) (-> math-cam d) cam-fov-mult)
)
(set! hvdf-x 2048.000000)
(set! hvdf-y 2048.000000)
(set! 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)
)
)
)
(set! hvdf-z (* 0.500000 (+ very-far very-near)))
(set! (-> math-cam hmge-scale data 0) (/ 1.000000 (-> math-cam x-clip)))
(set! (-> math-cam hmge-scale data 1) (/ 1.000000 (-> math-cam y-clip)))
(set! (-> math-cam hmge-scale data 2) (/ 1.000000 mid-range))
(set! (-> math-cam hmge-scale data 3) (/ 1.000000 fog-at-d))
(set! (-> math-cam inv-hmge-scale data 0) (-> math-cam x-clip))
(set! (-> math-cam inv-hmge-scale data 1) (-> math-cam y-clip))
(set! (-> math-cam inv-hmge-scale data 2) mid-range)
(set! (-> math-cam inv-hmge-scale data 3) fog-at-d)
(set! (-> math-cam hvdf-off data 0) hvdf-x)
(set! (-> math-cam hvdf-off data 1) hvdf-y)
(set! (-> math-cam hvdf-off data 2) hvdf-z)
(set! (-> math-cam hvdf-off data 3) hvdf-w)
(set! (-> math-cam guard data 0) (/ (-> math-cam x-clip) (-> math-cam x-pix)))
(set! (-> math-cam guard data 1) (/ (-> math-cam y-clip) (-> math-cam y-pix)))
(set! (-> math-cam guard data 2) 1.000000)
(set! (-> math-cam guard data 3) 1.000000)
(set! (-> math-cam isometric data 14) (- 16777215.000000 hvdf-z))
(set! (-> math-cam isometric data 15) fog-at-d)
(set! persp-xx (-> math-cam perspective data 0))
(set! persp-yy (-> math-cam perspective data 5))
(set! persp-x (* (the-as float #xbffff2e5) (-> math-cam perspective data 0)))
(set! sprite-row-0 (-> math-cam sprite-2d))
(set! (-> sprite-row-0 data 0) persp-x)
(set! (-> sprite-row-0 data 1) 0.000000)
(set! (-> sprite-row-0 data 2) 0.000000)
(set! (-> sprite-row-0 data 3) 0.000000)
(set! sprite-row-1 (&-> math-cam sprite-2d data 4))
(set! (-> sprite-row-1 0) 0.000000)
(set! (-> sprite-row-1 1) (- (* (/ persp-yy persp-xx) persp-x)))
(set! (-> sprite-row-1 2) 0.000000)
(set! (-> sprite-row-1 3) 0.000000)
(set! sprite-row-2 (&-> math-cam sprite-2d data 8))
(set! (-> sprite-row-2 0) 0.000000)
(set! (-> sprite-row-2 1) 0.000000)
(set! (-> sprite-row-2 2) (- persp-x))
(set! (-> sprite-row-2 3) 0.000000)
(set! sprite-row-3 (&-> math-cam sprite-2d data 12))
(set! (-> sprite-row-3 0) 0.000000)
(set! (-> sprite-row-3 1) 0.000000)
(set! (-> sprite-row-3 2) (* 500000000.000000 persp-x))
(set! (-> sprite-row-3 3) (* (* 60.000000 persp-x) (-> math-cam pfog0)))
(set! v1-15 (-> math-cam sprite-2d-hvdf))
(set! a0-10 (-> math-cam hvdf-off))
;;(.lq a0-11 0 a0-10)
;;(.sq a0-11 0 v1-15)
(rlet ((a0-11 :class vf))
(.lvf a0-11 a0-10)
(.svf v1-15 a0-11)
)
(set! (-> math-cam sprite-2d-hvdf data 0) 2048.000000)
(set! (-> math-cam sprite-2d-hvdf data 1) 2048.000000)
(set! (-> math-cam sprite-2d-hvdf data 2) (-> math-cam hvdf-off data 2))
(set! (-> math-cam pfog0) fog-at-d)
(set! (-> math-cam pfog1) hvdf-w)
;; unused
;;(set! v1-17 0)
;;(set! v1-19 (shl #x301ec000 32))
;;(.pcpyld v1-20 r0-0 v1-19)
;;(set! v1-22 (shl #x303ec000 32))
;;(.pcpyld v1-23 r0-0 v1-22)
(set! pfog (-> math-cam pfog0))
(set! vis-gif-0 (-> math-cam vis-gifs 0))
(set! (-> vis-gif-0 fog0) (the-as uint pfog))
(set! (-> vis-gif-0 strip) #x301e4000)
(set! (-> vis-gif-0 regs) 1042)
(set! (-> vis-gif-0 fan) #x301ec000)
(set! vis-gif-1 (-> math-cam vis-gifs 1))
(set! (-> vis-gif-1 fog0) (the-as uint pfog))
(set! a1-5 (shl #x20164000 32))
;;(.pcpyld a1-6 r0-0 a1-5) no effect
(set! (-> vis-gif-1 strip) a1-5)
(set! (-> vis-gif-1 regs) 65)
(set! (-> vis-gif-1 fan) #x301ec000)
(set! vis-gif-1-again (-> math-cam vis-gifs 0))
(set! (-> vis-gif-1-again fog0) (the-as uint pfog))
(set! (-> vis-gif-1-again strip) #x303e4000)
(set! (-> vis-gif-1-again regs) 1042)
(set! (-> vis-gif-1-again fan) #x303ec000)
(set! vis-gif-1-again-again (-> math-cam vis-gifs 0))
(set! (-> vis-gif-1-again-again fog0) (the-as uint pfog))
(set! (-> vis-gif-1-again-again strip) #x303e4000)
(set! (-> vis-gif-1-again-again regs) 1042)
(set! (-> vis-gif-1-again-again fan) #x303ec000)
(if (nonzero? sprite-distorter-generate-tables)
(sprite-distorter-generate-tables)
)
math-cam
)
(defmethod new math-camera ((allocation symbol) (type-to-make type))
"Allocate and initialize a math-camera.
NOTE: the result is full of nans due to fov-correction-factor being unset and defaulting to 0.
This matches what I remember from PS2 emulator stuff."
(local-vars (v1-2 vector) (obj math-camera))
(set! obj (object-new allocation type-to-make (the-as int (-> type-to-make size))))
(set! (-> obj d) 1024.000000) ;; near plane
(set! (-> obj f) 40960000.000000) ;; far plane (4096 meters)
(set! (-> obj fov) (the-as float #x46360b61)) ;; 64 degrees
(set! (-> obj x-pix) 256.000000)
;; not sure what this is, but it seems like there's a 4x wide clipping plane called "b"
(set! (-> obj x-clip) 1024.000000)
(set! (-> obj y-pix) 112.000000)
;; again, 4x wide clippin gthing
(set! (-> obj y-clip) 448.000000)
;; start fog at 10 meters
(set! (-> obj fog-start) 40960.000000)
;; end fog at 200 meters
(set! (-> obj fog-end) 819200.000000)
;; are these the actual fog values used?
(set! (-> obj fog-max) 255.000000)
(set! (-> obj fog-min) 150.000000)
(matrix-identity! (-> obj inv-camera-rot))
(matrix-identity! (-> obj camera-rot))
;;(set! v1-2 (-> obj trans))
;;(.sqc2 vf0 0 v1-2)
(vector-zero! (-> obj trans))
(set! (-> obj isometric data 0) 1.000000) ;; xx
(set! (-> obj isometric data 5) 0.500000) ;; yy
(set! (-> obj isometric data 10) -1.000000) ;; zz
(set! (-> obj reset) 1)
(set! (-> obj smooth-step) 0.000000)
(set! (-> obj smooth-t) 0.000000)
;; setup initial math camera
(update-math-camera obj 'ntsc 'aspect4x3)
)
(define *math-camera* (new 'global 'math-camera))