Files
jak-project/goal_src/jak1/engine/anim/joint.gc
T
water111 637990314b wip: better stack var support (#4222)
Closes #736

---------

Co-authored-by: Hat Kid <6624576+Hat-Kid@users.noreply.github.com>
2026-04-19 00:14:44 +02:00

1438 lines
61 KiB
Common Lisp

;;-*-Lisp-*-
(in-package goal)
(bundles "ENGINE.CGO" "GAME.CGO")
(require "engine/entity/res.gc")
(require "engine/gfx/background/subdivide-h.gc")
(require "engine/math/transformq.gc")
(require "engine/anim/joint-h.gc")
(require "engine/data/art-h.gc")
(require "engine/anim/mspace-h.gc")
(require "engine/game/game-h.gc")
;; a joint is just used to store the tree structure of a skeleton + bind pose.
;; it's mostly used as a more user-friendly interface
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; experimental new joint decompressor
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define *use-new-decompressor* #t)
;; this was re-written in GOAL. Despite being not well optimized, it ends up being faster
;; than the original.
;; request to decompress data from an animation
(deftype joint-decomp-request (structure)
((jacc joint-anim-compressed-control)
(frame int)
(frame-interp float)
(amount float)))
(deftype blend-tree-stack-frame (structure)
((weights float 24)
(quads vector 6 :inline :overlay-at weights)))
(deftype new-joint-decompressor-work (structure)
((requests joint-decomp-request 24 :inline)
(num-requests int32)
(blend-stack blend-tree-stack-frame 4 :inline))
(:methods
(eval-blend-tree! (_type_ joint-control) none)
(output-blend-tree! (_type_ joint-control) none)
(build-requests! (_type_ joint-control) none)
(init-frame! (_type_ joint-anim-frame int) none)
(process-request! (_type_ joint-decomp-request joint-anim-frame int) none)
(process-requests! (_type_ joint-anim-frame int) none)
(finalize-frame! (_type_ joint-anim-frame int) none)))
(define *new-joint-decompressor-work* (new 'global 'new-joint-decompressor-work))
(defun new-joint-decompressor ((dst joint-anim-frame) (num-joints int) (jc joint-control))
"Decompress a joint animation!"
;; determine anim weights, write them out to the joint-control for other stuff to see.
(eval-blend-tree! *new-joint-decompressor-work* jc)
(output-blend-tree! *new-joint-decompressor-work* jc)
;; figure out which animations need decompression
(build-requests! *new-joint-decompressor-work* jc)
;; run the decompression
(init-frame! *new-joint-decompressor-work* dst num-joints)
(process-requests! *new-joint-decompressor-work* dst num-joints)
(finalize-frame! *new-joint-decompressor-work* dst num-joints)
(none))
(defmethod eval-blend-tree! ((this new-joint-decompressor-work) (jc joint-control))
"Evaluate weights of all channels, producing the final per-animation weights in the first stack-frame."
(let ((num-channels (-> jc active-channels))
(stack-top 0))
(when (> num-channels 24)
(break!) ;; insufficient weights per stack frame
)
;; loop over channels
(dotimes (chan-idx num-channels)
(let ((chan (-> jc channel chan-idx)))
(case (-> chan command)
(('push) ;; push new anim to stack frame
(when (> stack-top 4)
(break!) ;; insufficient stack frames.
)
;; init all weights to zero:
(let ((new-frame (-> this blend-stack stack-top)))
(vector-zero! (-> new-frame quads 0))
(vector-zero! (-> new-frame quads 1))
(vector-zero! (-> new-frame quads 2))
(vector-zero! (-> new-frame quads 3))
(vector-zero! (-> new-frame quads 4))
(vector-zero! (-> new-frame quads 5))
;; except for this channel
(set! (-> new-frame weights chan-idx) 1.0))
(+! stack-top 1) ;; bump stack pointer!
)
;; blend case: note that push1/stack1 always are a pair, so we can treat push1 as blend and ignore
;; the stack1 as an optimization.
(('blend 'push1)
(let* ((sf (-> this blend-stack (- stack-top 1))) ;; modify most recent stack frame
(new-weight (-> chan frame-interp))
(old-weight (- 1.0 new-weight)))
;; do the multiplies:
(rlet ((temp :class vf)
(weight-vec :class vf))
(.mov weight-vec old-weight)
(dotimes (i 6)
(.lvf temp (&-> sf quads i quad))
(.mul.x.vf temp temp weight-vec)
(.svf (&-> sf quads i quad) temp))
(+! (-> sf weights chan-idx) new-weight))))
;; stack case: pop two frames, add together, push result.
(('stack)
(let* ((sf0 (-> this blend-stack (- stack-top 1)))
(sf1 (-> this blend-stack (- stack-top 2)))
(weight0 (-> chan frame-interp))
(weight1 (- 1.0 weight0)))
(rlet ((temp0 :class vf)
(temp1 :class vf)
(weight0-vec :class vf)
(weight1-vec :class vf))
(.mov weight0-vec weight0)
(.mov weight1-vec weight1)
(dotimes (i 6)
(.lvf temp0 (&-> sf0 quads i quad))
(.lvf temp1 (&-> sf1 quads i quad))
(.mul.x.vf temp0 temp0 weight0-vec)
(.mul.x.vf temp1 temp1 weight1-vec)
(.add.vf temp0 temp0 temp1)
(.svf (&-> sf1 quads i quad) temp0)))
(-! stack-top 1) ;; pop stack frame
))))))
(none))
(defmethod output-blend-tree! ((this new-joint-decompressor-work) (jc joint-control))
"Copy result of the blend tree evaluation into the joint-control."
(let ((num-channels (-> jc active-channels)))
(dotimes (chan-idx num-channels)
(set! (-> jc channel chan-idx inspector-amount) (-> this blend-stack 0 weights chan-idx))))
(none))
(defmethod build-requests! ((this new-joint-decompressor-work) (jc joint-control))
"Use the anim weights computed by eval-blend-tree! to build decompression requests"
(set! (-> this num-requests) 0)
(let ((num-channels (-> jc active-channels)))
(dotimes (chan-idx num-channels)
(let ((weight (-> this blend-stack 0 weights chan-idx))
(chan (-> jc channel chan-idx)))
(when (> weight 0.001) ;; only both if weight is nonzero
(let* ((req (-> this requests (-> this num-requests))) ;; request to create
(jacc (-> chan frame-group frames)) ;; compressed animation
(frame-num (-> chan frame-num)) ;; floating-point frame (eg 1.23)
(base-frame (the int frame-num)) ;; integer round-down frame (eg 1)
(frac-frame (- frame-num (the float base-frame))) ;; interp to next frame (eg 0.23)
(last-frame (the int (- (-> jacc num-frames) 1))))
(+! (-> this num-requests) 1)
;; check our frame group is valid
;; TODO
;; make sure we didn't go off the end of the animation:
(when (>= base-frame last-frame)
(set! frac-frame 0.0)
(set! base-frame last-frame))
;; set up request
(set! (-> req jacc) jacc)
(set! (-> req frame) base-frame)
(set! (-> req frame-interp) frac-frame)
(set! (-> req amount) weight))))))
(none))
(defmethod init-frame! ((this new-joint-decompressor-work) (output-frame joint-anim-frame) (num-joints int))
"Initialize an output frame by zeroing the data."
(let ((num-qwc 8) ;; 2x matrix, each 4 qw
(data (the (pointer uint128) output-frame)))
(when (> num-joints 2) ;; we have transformq's
(+! num-qwc (* 3 (- num-joints 2))))
(let ((data-end (&+ data (* num-qwc 16))))
(rlet ((zero :class vf))
(.xor.vf zero zero zero)
(while (!= data data-end) ;; this loop is 5 instructions :)
(.svf data zero)
(&+! data 16)))))
(none))
(defmethod process-requests! ((this new-joint-decompressor-work) (output-frame joint-anim-frame) (num-joints int))
"Decompress all pending animation requests."
(dotimes (i (-> this num-requests))
(process-request! this (-> this requests i) output-frame num-joints))
(set! (-> this num-requests) 0)
(none))
(defmacro fderef-s16 (ptr)
`(the float (-> (the (pointer int16) ,ptr))))
(defmacro deref-f32 (ptr)
`(-> (the (pointer float) ,ptr)))
(defconstant QUAT_SCALE 0.000030517578125)
(defconstant SCALE_SCALE 0.000244140625)
(defun add-scaled-matrix! ((dest matrix) (src matrix) (scale float))
(dotimes (i 16)
(+! (-> dest data i) (* scale (-> src data i)))))
(defun decomp-fixed ((output-frame joint-anim-frame) (num-joints int) (anim joint-anim-compressed-fixed) (amount float))
"Decompress the fixed part."
(let* ((mbits (-> anim hdr matrix-bits))
(data (the pointer (&-> anim data 0 quad)))
(data64 (the (pointer uint64) (&+ data (-> anim offset-64))))
(data32 (the (pointer uint32) (&+ data (-> anim offset-32))))
(data16 (the (pointer uint16) (&+ data (-> anim offset-16))))
(ctrl-ptr (-> anim hdr control-bits)))
;; process matrix:
(when (zero? (logand mbits 1))
;; matrix comes from fixed data
(add-scaled-matrix! (-> output-frame matrices 0) (the matrix data64) amount)
(&+! data64 64))
(when (zero? (logand mbits 2))
;; matrix comes from fixed data
(add-scaled-matrix! (-> output-frame matrices 1) (the matrix data64) amount)
(&+! data64 64))
;; process tq's
(dotimes (tqi num-joints) ;; TODO - not sure if this is too many??
(let* ((ctrl-idx (/ tqi 8))
(ctrl-shift (* 4 (mod tqi 8)))
(ctrl (logand #b1111 (sar (-> ctrl-ptr ctrl-idx) ctrl-shift)))
;(tq (-> output-frame data tqi))
(tq (-> (the (inline-array transformq) (-> output-frame data)) tqi)))
;; TRANS
(when (zero? (logand ctrl #b0001))
;; we have trans
(cond
((nonzero? (logand ctrl #b1000))
;; big trans
(+! (-> tq trans x) (* amount (deref-f32 data64)))
(&+! data64 4)
(+! (-> tq trans y) (* amount (deref-f32 data64)))
(&+! data64 4)
(+! (-> tq trans z) (* amount (deref-f32 data32)))
(&+! data32 4))
(else
;; little trans
(+! (-> tq trans x) (* amount (fderef-s16 data32) 4.))
(&+! data32 2)
(+! (-> tq trans y) (* amount (fderef-s16 data32) 4.))
(&+! data32 2)
(+! (-> tq trans z) (* amount (fderef-s16 data16) 4.))
(&+! data16 2))))
;; QUAT
(when (zero? (logand ctrl #b0010))
(let ((temp (new 'stack-no-clear 'vector)))
(set! (-> temp x) (fderef-s16 data64))
(&+! data64 2)
(set! (-> temp y) (fderef-s16 data64))
(&+! data64 2)
(set! (-> temp z) (fderef-s16 data64))
(&+! data64 2)
(set! (-> temp w) (fderef-s16 data64))
(&+! data64 2)
(let ((dot (+ (* (-> temp x) (-> tq quat x))
(* (-> temp y) (-> tq quat y))
(* (-> temp z) (-> tq quat z))
(* (-> temp w) (-> tq quat w)))))
(when (< dot 0.0)
(*! (-> temp x) -1.)
(*! (-> temp y) -1.)
(*! (-> temp z) -1.)
(*! (-> temp w) -1.))
(+! (-> tq quat x) (* amount (-> temp x) QUAT_SCALE))
(+! (-> tq quat y) (* amount (-> temp y) QUAT_SCALE))
(+! (-> tq quat z) (* amount (-> temp z) QUAT_SCALE))
(+! (-> tq quat w) (* amount (-> temp w) QUAT_SCALE)))))
;; SCALE
(when (zero? (logand ctrl #b0100))
(+! (-> tq scale x) (* amount (fderef-s16 data32) SCALE_SCALE))
(&+! data32 2)
(+! (-> tq scale y) (* amount (fderef-s16 data32) SCALE_SCALE))
(&+! data32 2)
(+! (-> tq scale z) (* amount (fderef-s16 data16) SCALE_SCALE))
(&+! data16 2)))))
(none))
(defun decomp-frame ((output-frame joint-anim-frame)
(num-joints int)
(anim joint-anim-compressed-frame)
(amount float)
(hdr joint-anim-compressed-hdr))
"Decompress the fixed part."
(let* ((mbits (-> hdr matrix-bits))
(data (the pointer (-> anim data)))
(data64 (the (pointer uint64) (&+ data (-> anim offset-64))))
(data32 (the (pointer uint32) (&+ data (-> anim offset-32))))
(data16 (the (pointer uint16) (&+ data (-> anim offset-16))))
(ctrl-ptr (-> hdr control-bits)))
;; process matrix:
(when (nonzero? (logand mbits 1))
;; matrix comes from fixed data
(add-scaled-matrix! (-> output-frame matrices 0) (the matrix data64) amount)
(&+! data64 64))
(when (nonzero? (logand mbits 2))
;; matrix comes from fixed data
(add-scaled-matrix! (-> output-frame matrices 1) (the matrix data64) amount)
(&+! data64 64))
;; process tq's
(dotimes (tqi num-joints) ;; TODO - not sure if this is too many??
(let* ((ctrl-idx (/ tqi 8))
(ctrl-shift (* 4 (mod tqi 8)))
(ctrl (logand #b1111 (sar (-> ctrl-ptr ctrl-idx) ctrl-shift)))
;(tq (-> output-frame data tqi))
(tq (-> (the (inline-array transformq) (-> output-frame data)) tqi)))
;; TRANS
(when (nonzero? (logand ctrl #b0001))
;; we have trans
(cond
((nonzero? (logand ctrl #b1000))
;; big trans
(+! (-> tq trans x) (* amount (deref-f32 data64)))
(&+! data64 4)
(+! (-> tq trans y) (* amount (deref-f32 data64)))
(&+! data64 4)
(+! (-> tq trans z) (* amount (deref-f32 data32)))
(&+! data32 4))
(else
;; little trans
(+! (-> tq trans x) (* amount (fderef-s16 data32) 4.))
(&+! data32 2)
(+! (-> tq trans y) (* amount (fderef-s16 data32) 4.))
(&+! data32 2)
(+! (-> tq trans z) (* amount (fderef-s16 data16) 4.))
(&+! data16 2))))
;; QUAT
(when (nonzero? (logand ctrl #b0010))
(let ((temp (new 'stack-no-clear 'vector)))
(set! (-> temp x) (fderef-s16 data64))
(&+! data64 2)
(set! (-> temp y) (fderef-s16 data64))
(&+! data64 2)
(set! (-> temp z) (fderef-s16 data64))
(&+! data64 2)
(set! (-> temp w) (fderef-s16 data64))
(&+! data64 2)
(let ((dot (+ (* (-> temp x) (-> tq quat x))
(* (-> temp y) (-> tq quat y))
(* (-> temp z) (-> tq quat z))
(* (-> temp w) (-> tq quat w)))))
(when (< dot 0.0)
(*! (-> temp x) -1.)
(*! (-> temp y) -1.)
(*! (-> temp z) -1.)
(*! (-> temp w) -1.))
(+! (-> tq quat x) (* amount (-> temp x) QUAT_SCALE))
(+! (-> tq quat y) (* amount (-> temp y) QUAT_SCALE))
(+! (-> tq quat z) (* amount (-> temp z) QUAT_SCALE))
(+! (-> tq quat w) (* amount (-> temp w) QUAT_SCALE)))))
;; SCALE
(when (nonzero? (logand ctrl #b0100))
(+! (-> tq scale x) (* amount (fderef-s16 data32) SCALE_SCALE))
(&+! data32 2)
(+! (-> tq scale y) (* amount (fderef-s16 data32) SCALE_SCALE))
(&+! data32 2)
(+! (-> tq scale z) (* amount (fderef-s16 data16) SCALE_SCALE))
(&+! data16 2)))))
(none))
(defmethod process-request! ((this new-joint-decompressor-work) (request joint-decomp-request) (output-frame joint-anim-frame) (num-joints int))
"Decompress a single animation, adding to accumulator"
;; first, the fixed part
(decomp-fixed output-frame num-joints (-> request jacc fixed) (-> request amount))
;; base frame
(decomp-frame output-frame
num-joints
(-> request jacc data (-> request frame))
(* (- 1.0 (-> request frame-interp)) (-> request amount))
(-> request jacc fixed hdr))
;; interpolate to next frame
(cond
((!= 0.0 (-> request frame-interp))
(decomp-frame output-frame
num-joints
(-> request jacc data (+ 1 (-> request frame)))
(* (-> request frame-interp) (-> request amount))
(-> request jacc fixed hdr)))
(else))
(none))
(defmethod finalize-frame! ((this new-joint-decompressor-work) (output-frame joint-anim-frame) (num-joints int))
(when (<= num-joints 2)
(return #f))
(dotimes (tqi (- num-joints 2))
(let ((tq (-> (the (inline-array transformq) (-> output-frame data)) tqi)))
(set! (-> tq trans w) 1.0)
(set! (-> tq scale w) 1.0)
(quaternion-normalize! (-> tq quat))))
(none))
;; DECOMP BEGINS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Basic Methods for joint/joint-control
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmethod print ((this joint))
(format #t "#<~A ~S ~D @ #x~X>" (-> this type) (-> this name) (-> this number) this)
this)
(defmethod mem-usage ((this joint) (usage memory-usage-block) (flags int))
(set! (-> usage length) (max 66 (-> usage length)))
(set! (-> usage data 65 name) "joint")
(+! (-> usage data 65 count) 1)
(let ((v1-6 (asize-of this))) (+! (-> usage data 65 used) v1-6) (+! (-> usage data 65 total) (logand -16 (+ v1-6 15))))
this)
(defmethod print ((this joint-anim))
(format #t "#<~A ~S ~D [~D] @ #x~X>" (-> this type) (-> this name) (-> this number) (-> this length) this)
this)
(defmethod length ((this joint-anim))
(-> this length))
(defmethod inspect ((this joint-anim-matrix))
(format #t "[~8x] ~A~%" this (-> this type))
(format #t "~Tname: ~A~%" (-> this name))
(format #t "~Tnumber: ~D~%" (-> this number))
(format #t "~Tdata[~D]: @ #x~X~%" (-> this length) (-> this data))
this)
(defmethod asize-of ((this joint-anim-matrix))
(the-as int (+ (-> joint-anim-matrix size) (* (-> this length) 64))))
(defmethod inspect ((this joint-anim-transformq))
(format #t "[~8x] ~A~%" this (-> this type))
(format #t "~Tname: ~A~%" (-> this name))
(format #t "~Tnumber: ~D~%" (-> this number))
(format #t "~Tdata[~D]: @ #x~X~%" (-> this length) (-> this data))
(dotimes (s5-0 (-> this length))
(format #t "~T [~D] ~`transformq`P~%" s5-0 (-> this data s5-0)))
this)
(defmethod asize-of ((this joint-anim-transformq))
(the-as int (+ (-> joint-anim-transformq size) (* 48 (-> this length)))))
(defmethod asize-of ((this joint-anim-drawable))
(the-as int (+ (-> joint-anim-drawable size) (* (-> this length) 4))))
(defun joint-anim-login ((arg0 joint-anim-drawable))
(dotimes (s5-0 (-> arg0 length))
(if (-> arg0 data s5-0) (login (-> arg0 data s5-0))))
arg0)
(defun joint-anim-inspect-elt ((arg0 joint-anim) (arg1 float))
"Inspect a single element in a joint anim. The float is rounded to an int."
(case (-> arg0 type)
((joint-anim-matrix)
((method-of-type matrix inspect) (the-as matrix (-> (the-as joint-anim-matrix arg0) data (the int arg1) vector))))
((joint-anim-transformq) (format #t "~`transform`P~%" (-> (the-as joint-anim-transformq arg0) data (the int arg1)))))
arg0)
(defmethod mem-usage ((this joint-anim-drawable) (usage memory-usage-block) (flags int))
(set! (-> usage length) (max 77 (-> usage length)))
(set! (-> usage data 76 name) "joint-anim-drawable")
(+! (-> usage data 76 count) 1)
(let ((v1-6 (asize-of this))) (+! (-> usage data 76 used) v1-6) (+! (-> usage data 76 total) (logand -16 (+ v1-6 15))))
(dotimes (s3-0 (-> this length))
(mem-usage (-> this data s3-0) usage flags))
this)
(defun jacc-mem-usage ((arg0 joint-anim-compressed-control) (arg1 memory-usage-block) (arg2 int))
(set! (-> arg1 length) (max 68 (-> arg1 length)))
(set! (-> arg1 data 67 name) "joint-anim-compressed-control")
(+! (-> arg1 data 67 count) 1)
(let ((v1-7 (+ (* (-> arg0 num-frames) 4) 16)))
(+! (-> arg1 data 67 used) v1-7)
(+! (-> arg1 data 67 total) (logand -16 (+ v1-7 15))))
(set! (-> arg1 length) (max 69 (-> arg1 length)))
(set! (-> arg1 data 68 name) "joint-anim-fixed")
(+! (-> arg1 data 68 count) 1)
(let ((v1-17 (+ (-> arg0 fixed-qwc) 16)))
(+! (-> arg1 data 68 used) v1-17)
(+! (-> arg1 data 68 total) (logand -16 (+ v1-17 15))))
(dotimes (v1-21 (the-as int (-> arg0 num-frames)))
(set! (-> arg1 length) (max 70 (-> arg1 length)))
(set! (-> arg1 data 69 name) "joint-anim-frame")
(+! (-> arg1 data 69 count) 1)
(let ((a2-15 (* (-> arg0 frame-qwc) 16)))
(+! (-> arg1 data 69 used) a2-15)
(+! (-> arg1 data 69 total) (logand -16 (+ a2-15 15)))))
arg0)
(defmethod print ((this joint-control-channel))
(format #t "#<joint-control-channel ~A ~A ~F @ #x~X>" (-> this command) (-> this frame-group) (-> this frame-num) this)
this)
(defmethod asize-of ((this joint-control))
(the-as int (+ (-> this type size) (* 48 (-> this allocated-length)))))
(defmethod new joint-control ((allocation symbol) (type-to-make type) (arg0 int))
"Create a new joint-control with enough room for the given number of channels"
(let ((v0-0 (object-new allocation type-to-make (the-as int (+ (-> type-to-make size) (* 48 arg0))))))
(set! (-> v0-0 allocated-length) arg0)
(set! (-> v0-0 active-channels) 0)
(set! (-> v0-0 root-channel) (-> v0-0 channel))
(set! (-> v0-0 generate-frame-function) create-interpolated-joint-animation-frame)
(set! (-> v0-0 prebind-function) #f)
(set! (-> v0-0 postbind-function) #f)
(set! (-> v0-0 effect) #f)
(dotimes (v1-4 arg0)
(set! (-> v0-0 channel v1-4 parent) v0-0))
(set! (-> v0-0 blend-index) -1)
v0-0))
(defmethod debug-print-frames ((this joint-control-channel))
"Print the current frame of each joint on this channel.
Note: this only appears to work for uncompressed joint animations."
(let ((s5-0 (-> this frame-group))
(f30-0 (-> this frame-num)))
(dotimes (s4-0 (length s5-0))
(format #t "joint ~A ~D " (-> s5-0 data s4-0 name) s4-0)
(joint-anim-inspect-elt (-> s5-0 data s4-0) f30-0)))
this)
(defmethod debug-print-channels ((this joint-control) (arg0 symbol))
"Print each active channel to the given stream."
(dotimes (s4-0 (-> this active-channels))
(let* ((v1-6 (if (and (-> this channel s4-0 frame-group) (nonzero? (-> this channel s4-0 frame-group)))
(-> this channel s4-0 frame-group))))
(format arg0
"ch:~2d ~C ~-35S f: ~6,,2f ~4,,2f ~4,,2f%~%"
s4-0 ;; channel index
(case (-> this channel s4-0 command) ;; how we got added.
(('push) 80)
(('push1) 112)
(('blend) 66)
(('stack) 83)
(('stack1) 115))
(if v1-6 (-> v1-6 name) "(none)") ;; name of anim (can be "none" in the real game)
(+ (* (-> this channel s4-0 frame-num) (if v1-6 (-> v1-6 artist-step) 1.0)) ;; frame number
(if v1-6 (-> v1-6 artist-base) 0.0))
(-> this channel s4-0 frame-interp)
(-> this channel s4-0 inspector-amount))))
0)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Art
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The "art" class is a super-general parent class for all art.
;; There's an "art-group" class, which typically contains all the animations
;; geometry, and shadow info for a character.
;; The most general art class shouldn't really be used for anything.
;; art-mesh-anim: not used
;; art-joint-anim: used for animations. Provides joint-anim-compressed and eye-anim.
(defmethod needs-link? ((this art))
#f)
(defmethod lookup-art ((this art) (arg0 string) (arg1 type))
"Look-up an art with the given name and type."
(the-as joint #f))
(defmethod lookup-idx-of-art ((this art) (arg0 string) (arg1 type))
"Look up the index of an art with the given name and type."
(the-as int #f))
(defmethod print ((this art))
(format #t "#<~A ~S :length ~D @ #x~X>" (-> this type) (-> this name) (-> this length) this)
this)
(defmethod length ((this art))
(-> this length))
(defmethod login ((this art))
;; not sure why we have to do this, but if the res-lump isn't properly set up to point to the tags
;; do it manually.
(if (and (-> this extra) (zero? (-> this extra tag)))
(set! (-> this extra tag) (&+ (the-as (pointer res-tag) (-> this extra)) 28)))
this)
(defmethod mem-usage ((this art-mesh-anim) (usage memory-usage-block) (flags int))
(set! (-> usage length) (max 72 (-> usage length)))
(set! (-> usage data 71 name) "art-mesh-anim")
(+! (-> usage data 71 count) 1)
(let ((v1-6 (asize-of this))) (+! (-> usage data 71 used) v1-6) (+! (-> usage data 71 total) (logand -16 (+ v1-6 15))))
(if (-> this extra) (mem-usage (-> this extra) usage (logior flags 512)))
(dotimes (s3-0 (-> this length))
(mem-usage (-> this data s3-0) usage flags))
this)
(defmethod mem-usage ((this art-joint-anim) (usage memory-usage-block) (flags int))
(set! (-> usage length) (max 75 (-> usage length)))
(set! (-> usage data 74 name) "art-joint-anim")
(+! (-> usage data 74 count) 1)
(let ((v1-6 (asize-of this))) (+! (-> usage data 74 used) v1-6) (+! (-> usage data 74 total) (logand -16 (+ v1-6 15))))
(if (-> this extra) (mem-usage (-> this extra) usage (logior flags 512)))
(jacc-mem-usage (-> this frames) usage flags)
(dotimes (s4-1 (-> this length))
(set! (-> usage length) (max 67 (-> usage length)))
(set! (-> usage data 66 name) "joint-anim-compressed")
(+! (-> usage data 66 count) 1)
(let ((v1-22 (asize-of (-> this data s4-1))))
(+! (-> usage data 66 used) v1-22)
(+! (-> usage data 66 total) (logand -16 (+ v1-22 15)))))
(when (and (nonzero? (-> this eye-anim-data)) (-> this eye-anim-data))
(set! (-> usage length) (max 109 (-> usage length)))
(set! (-> usage data 108 name) "eye-anim")
(+! (-> usage data 108 count) 1)
(let ((v1-41 (* (* (+ (-> this eye-anim-data max-frame) 1) 2) 8)))
(+! (-> usage data 108 used) v1-41)
(+! (-> usage data 108 total) (logand -16 (+ v1-41 15)))))
this)
(defmethod asize-of ((this art-joint-anim))
(the-as int (+ (-> art size) (* (-> this length) 4))))
(defmethod inspect ((this art-group))
"Print the arts in an art-group"
(format #t "[~8x] ~A~%" this (-> this type))
(format #t "~Tinfo: ~A~%" (-> this info))
(format #t "~Tlength: ~D~%" (-> this length))
(format #t "~Tname: ~A~%" (-> this name))
(format #t "~Textra: ~A~%" (-> this extra))
(format #t "~Tdata[~D]: @ #x~X~%" (-> this length) (-> this data))
(dotimes (s5-0 (-> this length))
(if (-> this data s5-0)
(format #t "~T [~D] ~A (~D bytes)~%" s5-0 (-> this data s5-0) (mem-size (-> this data s5-0) #f 0))
(format #t "~T [~D] ~A (~D bytes)~%" s5-0 (-> this data s5-0) 0)))
this)
(defmethod needs-link? ((this art-group))
"Does this art-group need to be added to the level's art group?
Some animations are streamed in, and need to be linked/unlinked to the level's list of art groups."
(the-as symbol
(and (-> this length)
(type-type? (-> this data 0 type) art-joint-anim)
(!= (-> this name) (-> (the-as art-joint-anim (-> this data 0)) master-art-group-name)))))
(defmethod lookup-art ((this art-group) (arg0 string) (arg1 type))
"Get the art with the given name and type. Set type to false if you don't care."
(the-as joint
(cond
(arg1
(let ((s3-0 (+ (length (-> this name)) 1)))
(dotimes (s2-0 (-> this length))
(if (and (-> this data s2-0) ;; entry is populated
(= (-> this data s2-0 type) arg1) ;; type is right
(or (name= arg0 (-> this data s2-0 name)) (string-charp= arg0 (&-> (-> this data s2-0 name) data s3-0))) ;; name is right. also seek past ag name, and try again.
)
(return (the-as joint (-> this data s2-0))))))
(the-as art-element #f))
(else
;; no type (also no weird after ag name check)
(dotimes (s4-1 (-> this length))
(if (and (-> this data s4-1) (name= arg0 (-> this data s4-1 name))) (return (the-as joint (-> this data s4-1)))))
(the-as art-element #f)))))
(defmethod lookup-idx-of-art ((this art-group) (arg0 string) (arg1 type))
"Get the index of the art with the given name and type. Set type to false if you don't care.
Will return #f if the art is not found."
(cond
(arg1
(let ((s3-0 (+ (length (-> this name)) 1)))
(dotimes (s2-0 (-> this length))
(if (and (-> this data s2-0)
(= (-> this data s2-0 type) arg1)
(or (name= arg0 (-> this data s2-0 name)) (string-charp= arg0 (&-> (-> this data s2-0 name) data s3-0))))
(return s2-0))))
(the-as int #f))
(else
(dotimes (s4-1 (-> this length))
(if (and (-> this data s4-1) (name= arg0 (-> this data s4-1 name))) (return s4-1)))
(the-as int #f))))
(defmethod login ((this art-group))
"Log in all the arts in a group."
(dotimes (s5-0 (-> this length))
(if (-> this data s5-0) (set! (-> this data s5-0) (login (-> this data s5-0)))))
this)
(defmethod mem-usage ((this art-group) (usage memory-usage-block) (flags int))
(set! (-> usage length) (max 71 (-> usage length)))
(set! (-> usage data 70 name) "art-group")
(+! (-> usage data 70 count) 1)
(let ((v1-6 (asize-of this))) (+! (-> usage data 70 used) v1-6) (+! (-> usage data 70 total) (logand -16 (+ v1-6 15))))
(if (-> this extra) (mem-usage (-> this extra) usage (logior flags 512)))
(dotimes (s3-0 (-> this length))
(if (-> this data s3-0) (mem-usage (-> this data s3-0) usage flags)))
this)
(defmethod relocate ((this art-group) (heap kheap) (name (pointer uint8)))
"Handle a loaded art-group."
(let ((s4-0 (clear *temp-string*)))
(string<-charp s4-0 name)
(set! this
(cond
((not this) (format 0 "ERROR: art-group ~A is not a valid file.~%" s4-0) (the-as art-group #f))
((not (type-type? (-> this type) art-group))
(format 0 "ERROR: art-group ~A is not a art-group.~%" s4-0)
(the-as art-group #f))
((not (file-info-correct-version? (-> this info) (file-kind art-group) 0)) (the-as art-group #f))
(else
(let ((s5-1 (-> *level* loading-level)))
(if (or (not s5-1) (= (-> s5-1 name) 'default)) (login this)) ;; not part of level load, just normal login.
(if s5-1 (set-loaded-art (-> s5-1 art-group) this))) ;; part of level load, add to level's ag, but don't log in yet.
this))))
(none))
(defmethod asize-of ((this art-mesh-geo))
(the-as int (+ (-> art size) (* (-> this length) 4))))
(defmethod mem-usage ((this art-mesh-geo) (usage memory-usage-block) (flags int))
(set! (-> usage length) (max 73 (-> usage length)))
(set! (-> usage data 72 name) "art-mesh-geo")
(+! (-> usage data 72 count) 1)
(let ((v1-6 (asize-of this))) (+! (-> usage data 72 used) v1-6) (+! (-> usage data 72 total) (logand -16 (+ v1-6 15))))
(if (-> this extra) (mem-usage (-> this extra) usage (logior flags 512)))
(dotimes (s3-0 (-> this length))
(mem-usage (-> this data s3-0) usage flags))
this)
(defmethod login ((this art-joint-anim))
(if (and (-> this extra) (zero? (-> this extra tag)))
(set! (-> this extra tag) (&+ (the-as (pointer res-tag) (-> this extra)) 28)))
this)
(defmethod asize-of ((this art-joint-geo))
(the-as int (+ (-> art size) (* (-> this length) 4))))
(defmethod lookup-art ((this art-joint-geo) (arg0 string) (arg1 type))
(cond
(arg1
(dotimes (s3-0 (-> this length))
(if (and (= (-> this data s3-0 type) arg1) (name= arg0 (-> this data s3-0 name))) (return (-> this data s3-0))))
(the-as joint #f))
(else
(dotimes (s4-1 (-> this length))
(if (name= arg0 (-> this data s4-1 name)) (return (-> this data s4-1))))
(the-as joint #f))))
(defmethod lookup-idx-of-art ((this art-joint-geo) (arg0 string) (arg1 type))
(cond
(arg1
(dotimes (s3-0 (-> this length))
(if (and (= (-> this data s3-0 type) arg1) (name= arg0 (-> this data s3-0 name))) (return s3-0)))
(the-as int #f))
(else (dotimes (s4-1 (-> this length)) (if (name= arg0 (-> this data s4-1 name)) (return s4-1))) (the-as int #f))))
(defmethod mem-usage ((this art-joint-geo) (usage memory-usage-block) (flags int))
(set! (-> usage length) (max 74 (-> usage length)))
(set! (-> usage data 73 name) "art-joint-geo")
(+! (-> usage data 73 count) 1)
(let ((v1-6 (asize-of this))) (+! (-> usage data 73 used) v1-6) (+! (-> usage data 73 total) (logand -16 (+ v1-6 15))))
(if (-> this extra) (mem-usage (-> this extra) usage (logior flags 512)))
(dotimes (s3-0 (-> this length))
(mem-usage (-> this data s3-0) usage flags))
this)
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Joint Control!
;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun joint-control-channel-eval ((arg0 joint-control-channel))
"Run the joint control num-func callback, remember the current time"
((-> arg0 num-func) arg0 (-> arg0 param 0) (-> arg0 param 1))
(set! (-> arg0 eval-time) (the-as uint (current-time)))
(none))
(defun joint-control-channel-eval! ((arg0 joint-control-channel) (arg1 (function joint-control-channel float float float)))
"Set the joint control num-func, and evaluate it."
(set! (-> arg0 num-func) arg1)
(arg1 arg0 (-> arg0 param 0) (-> arg0 param 1))
(set! (-> arg0 eval-time) (the-as uint (current-time)))
(none))
(defun joint-control-channel-group-eval! ((arg0 joint-control-channel) (arg1 art-joint-anim) (arg2 (function joint-control-channel float float float)))
"Set the joint control num-func, maybe update the anim, and maybe evaluate it."
(set! (-> arg0 num-func) arg2)
(cond
((= (-> arg0 command) 'stack))
(else
(if arg1 (set! (-> arg0 frame-group) arg1))
(arg2 arg0 (-> arg0 param 0) (-> arg0 param 1))
(set! (-> arg0 eval-time) (the-as uint (current-time)))))
0)
(defun joint-control-channel-group! ((arg0 joint-control-channel) (arg1 art-joint-anim) (arg2 (function joint-control-channel float float float)))
"Set the joint control num-func and maybe update the anim."
(set! (-> arg0 num-func) arg2)
(cond
((= (-> arg0 command) 'stack))
(arg1 (set! (-> arg0 frame-group) arg1)))
0)
(defun joint-control-copy! ((arg0 joint-control) (arg1 joint-control))
"Copy one joint control to another."
;; set fields
(set! (-> arg0 blend-index) (-> arg1 blend-index))
(set! (-> arg0 active-channels) (-> arg1 active-channels))
;; figure out which slot the source is, and remember that we're a copy.
(set! (-> arg0 root-channel)
(the-as (inline-array joint-control-channel)
(-> arg0 channel (/ (&- (the-as pointer (-> arg1 root-channel)) (the-as uint (the-as pointer (-> arg1 channel)))) 48))))
;; copy channels
(mem-copy! (the-as pointer (-> arg0 channel)) (the-as pointer (-> arg1 channel)) (* 48 (-> arg0 allocated-length)))
;; set parents of channels to point to the dest.
(dotimes (v1-7 (-> arg0 allocated-length))
(set! (-> arg0 channel v1-7 parent) arg0))
arg0)
;; ERROR: Failed load: (set! v1-29 (l.wu (+ a0-9 -4))) at op 75
(defun joint-control-remap! ((arg0 joint-control) (arg1 art-group) (arg2 art-group) (arg3 pair) (arg4 int) (arg5 string))
(let ((sv-16 (+ (length (-> arg2 name)) 1))
(sv-24 #t))
(let ((sv-32 arg4)
(sv-40 2))
(while (and (< sv-40 (-> arg1 length)) (!= (-> arg1 data sv-40 type) art-joint-anim))
(+! sv-40 1))
(dotimes (s2-1 (-> arg0 active-channels))
(let ((sv-48 (-> arg0 channel s2-1)))
(when (-> sv-48 frame-group)
(format (clear *temp-string*) "~S~G" arg5 (&+ (-> sv-48 frame-group name data) sv-16))
(when (not (null? arg3))
(let ((sv-52 (nassoc *temp-string* arg3)))
(when sv-52
(let* ((a0-9 sv-52)
(sv-56 (mod sv-32 (+ ((method-of-type (rtype-of a0-9) length) a0-9) -1))))
(format (clear *temp-string*) "~S" (ref sv-52 (+ sv-56 1)))))))
(let ((sv-64 (lookup-art arg1 *temp-string* art-joint-anim)))
(cond
(sv-64 (set! (-> sv-48 frame-group) (the-as art-joint-anim sv-64)))
(else
(set! (-> sv-48 frame-group) (the-as art-joint-anim (-> arg1 data sv-40)))
(set! (-> sv-48 frame-num) 0.0)
(set! sv-24 (the-as symbol #f)))))))))
sv-24))
(defun flatten-joint-control-to-spr ((arg0 joint-control))
"Take the current state of the given joint-control and upload it to the scratchpad
in the format that will be understood by the joint animation decompressor."
(rlet ((vf1 :class vf)
(vf10 :class vf)
(vf11 :class vf)
(vf12 :class vf)
(vf13 :class vf)
(vf14 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
(vf5 :class vf)
(vf6 :class vf)
(vf7 :class vf)
(vf8 :class vf)
(vf9 :class vf))
(let ((nb-channels (-> arg0 active-channels)))
(let ((f0-0 1.0) ;; one
(v1-0 0) ;; offset in spad
(a1-0 (-> (scratchpad-object terrain-context) work foreground joint-work flattened)) ;; start of data.
)
;; loop over active channels.
;;
(dotimes (a0-1 nb-channels)
(let ((a2-3 (-> arg0 channel a0-1)))
(case (-> a2-3 command)
(('push)
;; this adds a weight of 1 for this channel always.
;; note that the quads store 1 - weight, so we store 0's here.
(let ((a2-4 (&+ (the-as pointer a1-0) v1-0)))
(set! (-> a1-0 0 quad) (the-as uint128 0))
(set! (-> a1-0 1 quad) (the-as uint128 0))
(set! (-> a1-0 2 quad) (the-as uint128 0))
(set! (-> a1-0 3 quad) (the-as uint128 0))
(set! (-> a1-0 4 quad) (the-as uint128 0))
(set! (-> a1-0 5 quad) (the-as uint128 0))
;; and this thing stores the normal weight.
(set! (-> (the-as (pointer float) a2-4)) f0-0))
;; advance.
(set! a1-0 (the-as (inline-array vector) (-> a1-0 6))))
(('blend 'push1)
(let ((f1-0 (-> a2-3 frame-interp)))
(let ((a2-5 (- f0-0 f1-0))) (.mov vf1 a2-5))
(let ((a1-1 (the-as (inline-array vector) (-> a1-0 -6))))
(.lvf vf2 (&-> a1-1 0 quad))
(let ((a2-6 (&+ (the-as pointer a1-1) v1-0)))
(.lvf vf3 (&-> a1-1 1 quad))
(.lvf vf4 (&-> a1-1 2 quad))
(.lvf vf5 (&-> a1-1 3 quad))
(.lvf vf6 (&-> a1-1 4 quad))
(.lvf vf7 (&-> a1-1 5 quad))
(.mul.x.vf vf2 vf2 vf1)
(.mul.x.vf vf3 vf3 vf1)
(.mul.x.vf vf4 vf4 vf1)
(.mul.x.vf vf5 vf5 vf1)
(.mul.x.vf vf6 vf6 vf1)
(.mul.x.vf vf7 vf7 vf1)
(.svf (&-> a1-1 0 quad) vf2)
(.svf (&-> a1-1 1 quad) vf3)
(.svf (&-> a1-1 2 quad) vf4)
(.svf (&-> a1-1 3 quad) vf5)
(.svf (&-> a1-1 4 quad) vf6)
(.svf (&-> a1-1 5 quad) vf7)
(set! (-> (the-as (pointer float) a2-6)) (+ (-> (the-as (pointer float) a2-6) 0) f1-0)))
(set! a1-0 (the-as (inline-array vector) (-> a1-1 6))))))
(('stack)
(let* ((f2-2 (-> a2-3 frame-interp))
(f1-2 (- f0-0 f2-2))
(a1-2 (the-as (inline-array vector) (-> a1-0 -12))))
(let ((a2-7 f2-2)) (.mov vf1 a2-7))
(let ((a2-8 f1-2)) (.mov vf2 a2-8))
(.lvf vf3 (&-> a1-2 0 quad))
(.lvf vf4 (&-> a1-2 1 quad))
(.lvf vf5 (&-> a1-2 2 quad))
(.lvf vf6 (&-> a1-2 3 quad))
(.lvf vf7 (&-> a1-2 4 quad))
(.lvf vf8 (&-> a1-2 5 quad))
(.mul.x.vf vf3 vf3 vf2)
(.mul.x.vf vf4 vf4 vf2)
(.mul.x.vf vf5 vf5 vf2)
(.mul.x.vf vf6 vf6 vf2)
(.mul.x.vf vf7 vf7 vf2)
(.mul.x.vf vf8 vf8 vf2)
(.lvf vf9 (&-> a1-2 6 quad))
(.lvf vf10 (&-> a1-2 7 quad))
(.lvf vf11 (&-> a1-2 8 quad))
(.lvf vf12 (&-> a1-2 9 quad))
(.lvf vf13 (&-> a1-2 10 quad))
(.lvf vf14 (&-> a1-2 11 quad))
(.mul.x.vf vf9 vf9 vf1)
(.mul.x.vf vf10 vf10 vf1)
(.mul.x.vf vf11 vf11 vf1)
(.mul.x.vf vf12 vf12 vf1)
(.mul.x.vf vf13 vf13 vf1)
(.mul.x.vf vf14 vf14 vf1)
(.add.vf vf3 vf3 vf9)
(.add.vf vf4 vf4 vf10)
(.add.vf vf5 vf5 vf11)
(.add.vf vf6 vf6 vf12)
(.add.vf vf7 vf7 vf13)
(.add.vf vf8 vf8 vf14)
(.svf (&-> a1-2 0 quad) vf3)
(.svf (&-> a1-2 1 quad) vf4)
(.svf (&-> a1-2 2 quad) vf5)
(.svf (&-> a1-2 3 quad) vf6)
(.svf (&-> a1-2 4 quad) vf7)
(.svf (&-> a1-2 5 quad) vf8)
(set! a1-0 (the-as (inline-array vector) (-> a1-2 6)))))))
(+! v1-0 4)))
(let ((upl-idx 0))
(dotimes (ch nb-channels)
(when (< 0.001 (-> (scratchpad-object terrain-context) work foreground joint-work flatten-array ch))
(let* ((v1-9 (-> arg0 channel ch))
(s2-0 (-> v1-9 frame-group frames))
(f0-2 (-> v1-9 frame-num))
(s1-0 (the int f0-2))
(f30-0 (- f0-2 (the float s1-0))))
(let ((s0-0 (+ (-> s2-0 num-frames) -1)))
(if (not (-> v1-9 frame-group)) (format 0 "Channel ~D skel ~A frame-group is #f!!!~%" ch arg0))
(when (>= s1-0 (the-as int s0-0))
(set! f30-0 0.0)
(set! s1-0 (the-as int s0-0))))
(let ((v1-18 (-> (scratchpad-object terrain-context) work foreground joint-work uploads upl-idx)))
(set! (-> v1-18 fixed) (-> s2-0 fixed))
(set! (-> v1-18 fixed-qwc) (the-as int (-> s2-0 fixed-qwc)))
(set! (-> v1-18 frame) (-> s2-0 data s1-0))
(set! (-> v1-18 frame-qwc) (the-as int (if (= f30-0 0.0) (-> s2-0 frame-qwc) (* (-> s2-0 frame-qwc) 2))))
(set! (-> v1-18 amount) (-> (scratchpad-object terrain-context) work foreground joint-work flatten-array ch))
(set! (-> v1-18 interp) f30-0)))
(+! upl-idx 1)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work num-uploads) upl-idx))
(dotimes (v1-24 nb-channels)
(set! (-> arg0 channel v1-24 inspector-amount)
(-> (scratchpad-object terrain-context) work foreground joint-work flatten-array v1-24))))
0))
(defun matrix-from-joint-anim-frame ((arg0 joint-anim-compressed-control) (arg1 int) (arg2 int))
(let ((v1-1 (the-as object (-> arg0 fixed data)))
(v0-0 (the-as object (-> arg0 data arg2 data))))
(cond
((not (logtest? (-> arg0 fixed hdr matrix-bits) 1))
(set! v1-1
(cond
((zero? arg1) (return (the-as matrix v1-1)) v1-1)
(else (-> (the-as (inline-array vector) v1-1) 4)))))
((zero? arg1) (return (the-as matrix v0-0)))
(else (set! v0-0 (-> (the-as (inline-array vector) v0-0) 4))))
(if (not (logtest? (-> arg0 fixed hdr matrix-bits) 2)) (return (the-as matrix v1-1)))
(the-as matrix v0-0)))
(defun matrix-from-control-channel! ((arg0 matrix) (arg1 joint) (arg2 joint-control-channel))
(let ((s4-0 (-> arg2 frame-group))
(s5-0 (-> arg1 number)))
(if (>= s5-0 2) (format 0 "ERROR: Call to matrix-from-control-channel! on joint ~D~%" s5-0))
(let* ((f30-0 (fmax 0.0 (fmin (-> arg2 frame-num) (the float (+ (-> s4-0 data 0 length) -1)))))
(f0-1 f30-0))
(cond
((= (the float (the int f0-1)) f0-1)
(let* ((a2-3 (matrix-from-joint-anim-frame (-> s4-0 frames) s5-0 (the int f30-0)))
(v1-7 (-> a2-3 vector 0 quad))
(a0-3 (-> a2-3 vector 1 quad))
(a1-3 (-> a2-3 vector 2 quad))
(a2-4 (-> a2-3 vector 3 quad)))
(set! (-> arg0 vector 0 quad) v1-7)
(set! (-> arg0 vector 1 quad) a0-3)
(set! (-> arg0 vector 2 quad) a1-3)
(set! (-> arg0 vector 3 quad) a2-4))
arg0)
(else
(let ((s3-1 (matrix-from-joint-anim-frame (-> s4-0 frames) s5-0 (the int f30-0)))
(a2-7 (matrix-from-joint-anim-frame (-> s4-0 frames) s5-0 (+ (the int f30-0) 1)))
(f0-9 (- f30-0 (the float (the int f30-0)))))
(matrix-lerp! arg0 s3-1 a2-7 f0-9)))))))
(defun matrix-from-control-pair! ((arg0 matrix) (arg1 matrix) (arg2 joint))
(let ((f30-0 (-> arg1 vector 0 z)))
(cond
((>= 0.0 f30-0) (empty) arg0)
((>= f30-0 1.0) (matrix-from-control-channel! arg0 arg2 (the-as joint-control-channel arg1)))
(else
(let ((a2-3 (matrix-from-control-channel! (the-as matrix (-> (scratchpad-object terrain-context) work))
arg2
(the-as joint-control-channel arg1))))
(matrix-lerp! arg0 arg0 a2-3 f30-0))))))
(defun matrix-from-control! ((arg0 matrix-stack) (arg1 joint) (arg2 joint-control) (arg3 symbol))
(set! (-> arg0 top) (the-as matrix (-> arg0 data)))
;(set! arg3 'a)
(dotimes (s2-0 (-> arg2 active-channels))
(let* ((a2-1 (-> arg2 channel s2-0))
(v1-4 (-> a2-1 command))
(s1-0 64))
(cond
((and (= arg3 'no-push) (= v1-4 'push1))
(matrix-from-control-channel! (the-as matrix (&- (the-as pointer (-> arg0 top)) (the-as uint s1-0))) arg1 a2-1))
((and (= arg3 'no-push) (= v1-4 'stack))
(set! (-> arg0 top) (the-as matrix (&- (the-as pointer (-> arg0 top)) (the-as uint s1-0))))
(let* ((v1-10 (the-as matrix (&- (the-as pointer (-> arg0 top)) (the-as uint s1-0))))
(a3-1 (-> arg0 top))
(a0-10 (-> a3-1 vector 0 quad))
(a1-4 (-> a3-1 vector 1 quad))
(a2-2 (-> a3-1 vector 2 quad))
(a3-2 (-> a3-1 vector 3 quad)))
(set! (-> v1-10 vector 0 quad) a0-10)
(set! (-> v1-10 vector 1 quad) a1-4)
(set! (-> v1-10 vector 2 quad) a2-2)
(set! (-> v1-10 vector 3 quad) a3-2)))
((= v1-4 'push)
(matrix-from-control-channel! (-> arg0 top) arg1 a2-1)
(set! (-> arg0 top) (the-as matrix (+ (the-as uint (-> arg0 top)) s1-0)))
;(return (-> arg0 data 0))
)
((or (= v1-4 'blend) (= v1-4 'push1))
(matrix-from-control-pair! (the-as matrix (&- (the-as pointer (-> arg0 top)) (the-as uint s1-0)))
(the-as matrix a2-1)
arg1))
((= v1-4 'stack)
(set! (-> arg0 top) (the-as matrix (&- (the-as pointer (-> arg0 top)) (the-as uint s1-0))))
(let ((a1-8 (&- (the-as pointer (-> arg0 top)) (the-as uint s1-0)))
(v1-19 (-> arg0 top))
(f0-0 (-> a2-1 frame-interp)))
(matrix-lerp! (the-as matrix a1-8) (the-as matrix a1-8) v1-19 f0-0))))))
(the-as matrix (-> arg0 data)))
(defmethod reset-and-assign-geo! ((this cspace) (arg0 basic))
(set! (-> this parent) #f)
(set! (-> this joint) #f)
(set! (-> this geo) arg0)
(set! (-> this param0) #f)
(set! (-> this param1) #f)
(set! (-> this param2) #f)
this)
(defmethod new cspace ((allocation symbol) (type-to-make type) (arg0 basic))
(let ((t9-0 (method-of-type structure new))
(v1-1 type-to-make))
(-> type-to-make size)
((method-of-type cspace reset-and-assign-geo!) (the-as cspace (t9-0 allocation v1-1)) arg0)))
(defun cspace<-cspace! ((arg0 cspace) (arg1 cspace))
(let ((v0-0 (-> arg0 bone transform)))
(let* ((a2-0 (-> arg1 bone transform))
(v1-2 (-> a2-0 vector 0 quad))
(a0-1 (-> a2-0 vector 1 quad))
(a1-1 (-> a2-0 vector 2 quad))
(a2-1 (-> a2-0 vector 3 quad)))
(set! (-> v0-0 vector 0 quad) v1-2)
(set! (-> v0-0 vector 1 quad) a0-1)
(set! (-> v0-0 vector 2 quad) a1-1)
(set! (-> v0-0 vector 3 quad) a2-1))
v0-0))
(defun cspace<-rot-yxy! ((arg0 cspace) (arg1 transform))
(let ((s5-0 (-> arg0 bone transform)))
(matrix-rotate-yxy! s5-0 (-> arg1 rot))
(scale-matrix! s5-0 (-> arg1 scale) s5-0)))
(defun cspace<-transform-yxy! ((arg0 cspace) (arg1 transform))
(let ((s4-0 (-> arg0 bone transform))
(s5-0 (new 'stack-no-clear 'matrix))
(s3-0 (new 'stack-no-clear 'matrix)))
(matrix-identity! s4-0)
(matrix-translate! s4-0 (-> arg1 trans))
(matrix-rotate-yxy! s5-0 (-> arg1 rot))
(matrix*! s3-0 s5-0 s4-0)
(scale-matrix! s4-0 (-> arg1 scale) s3-0)))
(defun cspace<-transformq! ((arg0 cspace) (arg1 transformq))
(matrix<-transformq! (-> arg0 bone transform) arg1))
(defun cspace<-transformq+trans! ((arg0 cspace) (arg1 transformq) (arg2 vector))
(matrix<-transformq+trans! (-> arg0 bone transform) arg1 arg2))
(defun cspace<-transformq+world-trans! ((arg0 cspace) (arg1 transformq) (arg2 vector))
(matrix<-transformq+world-trans! (-> arg0 bone transform) arg1 arg2))
(defun cspace-calc-total-matrix! ((arg0 cspace) (arg1 matrix))
(matrix*! arg1 (-> arg0 bone transform) (-> *math-camera* camera-temp)))
(defun cspace<-matrix-no-push-joint! ((arg0 cspace) (arg1 joint-control))
(let ((v1-2 (matrix-from-control! (-> (scratchpad-object terrain-context) work foreground joint-work joint-stack)
(-> arg0 joint)
arg1
'no-push))
(v0-1 (-> arg0 bone transform)))
(let ((a0-4 (-> v1-2 vector 0 quad))
(a1-2 (-> v1-2 vector 1 quad))
(a2-1 (-> v1-2 vector 2 quad))
(v1-3 (-> v1-2 vector 3 quad)))
(set! (-> v0-1 vector 0 quad) a0-4)
(set! (-> v0-1 vector 1 quad) a1-2)
(set! (-> v0-1 vector 2 quad) a2-1)
(set! (-> v0-1 vector 3 quad) v1-3))
v0-1))
(defun cspace<-matrix-joint! ((arg0 cspace) (arg1 matrix))
(let ((v0-0 (-> arg0 bone transform)))
(let* ((a2-0 arg1)
(v1-1 (-> a2-0 vector 0 quad))
(a0-1 (-> a2-0 vector 1 quad))
(a1-1 (-> a2-0 vector 2 quad))
(a2-1 (-> a2-0 vector 3 quad)))
(set! (-> v0-0 vector 0 quad) v1-1)
(set! (-> v0-0 vector 1 quad) a0-1)
(set! (-> v0-0 vector 2 quad) a1-1)
(set! (-> v0-0 vector 3 quad) a2-1))
v0-0))
(defun cspace<-parented-matrix-joint! ((arg0 cspace) (arg1 matrix))
(matrix*! (-> arg0 bone transform) arg1 (-> arg0 parent bone transform)))
;; tricky ones:
;; cspace<-parented-transformq-joint!
;; -manually done, could also be mips2c if too slow
;; clear-frame-accumulator
;; - clear 128 bytes + 48*s2 bytes.
;; - probably should be C++.
;; normalize-frame-quaternions
;; - can mips2c
;; decompress-fixed-data-to-accumulator
;; - pretty big, should mips2c (jump table)
;; decompress-frame-data-to-accumulator
;; - pretty big, should mips2c (jump table)
;; decompress-frame-data-pair-to-accumulator
;; - pretty big, should mips2c (jump table)
;; make-joint-jump-tables
;; - gross
;; calc-animation-from-spr
;; - would be nice as goal.
;; all run by create-interpolated-joint-animation-frame
(def-mips2c cspace<-parented-transformq-joint! (function cspace transformq none))
; (defun cspace<-parented-transformq-joint! ((arg0 cspace) (arg1 transformq))
; (nop!)
; ;; the ops in these funcs were scrambled for pipeline optimization. screw that.
; ;; f0 = 1.0
; ;; a3 = -> arg0 parent (used once)
; (rlet ((acc :class vf)
; (vf0 :class vf) ;; unit
; (vf5 :class vf) ;; quat
; (vf15 :class vf) ;; trans
; (vf6 :class vf) ;; temp
; (vf2 :class vf) ;; temp
; (vf3 :class vf) ;; temp
; (vf4 :class vf) ;; temp
; (vf1 :class vf) ;; temp
; (vf7 :class vf) ;; temp
; (vf8 :class vf) ;; temp
; (vf9 :class vf) ;; temp
; (vf10 :class vf) ;; temp
; (vf11 :class vf) ;; temp
; (vf12 :class vf) ;; temp
; (vf13 :class vf) ;; temp
; (vf14 :class vf) ;; temp
; (vf16 :class vf) ;; temp
; (t1 :class vf)
; (t2 :class vf)
; (t3 :class vf)
; )
; (init-vf0-vector)
; (.lvf vf5 (-> arg1 quat))
; (.lvf vf15 (-> arg1 trans))
; (let ((t0 (-> arg0 parent bone))
; (a2 (-> arg0 bone))
; )
; (.add.vf vf6 vf5 vf5)
; ;; set vf2
; (.add.w.vf.x vf2 vf0 vf5)
; (.add.z.vf.y vf2 vf0 vf5)
; (.sub.y.vf.z vf2 vf0 vf5)
; (.sub.w.vf.w vf2 vf0 vf0)
; ;; set vf3
; (.sub.z.vf.x vf3 vf0 vf5)
; (.add.w.vf.y vf3 vf0 vf5)
; (.add.x.vf.z vf3 vf0 vf5)
; (.sub.w.vf.w vf3 vf0 vf0)
; ;; set vf4
; (.add.y.vf.x vf4 vf0 vf5)
; (.sub.x.vf.y vf4 vf0 vf5)
; (.add.w.vf.z vf4 vf0 vf5)
; (.sub.w.vf.w vf4 vf0 vf0)
; ;; outer prods
; (.outer.product.a.vf acc vf6 vf2)
; (.outer.product.b.vf vf2 vf2 vf6 acc)
; (.outer.product.a.vf acc vf6 vf3)
; (.outer.product.b.vf vf3 vf3 vf6 acc)
; (.outer.product.a.vf acc vf6 vf4)
; (.outer.product.b.vf vf4 vf4 vf6 acc)
; ;; add ones
; (.add.w.vf.x vf2 vf2 vf0)
; (.add.w.vf.y vf3 vf3 vf0)
; (.add.w.vf.z vf4 vf4 vf0)
; ;; things for cond blocks
; (.lvf vf7 (-> t0 transform vector 0))
; (.lvf vf8 (-> t0 transform vector 1))
; (.lvf vf9 (-> t0 transform vector 2))
; (.lvf vf10 (-> t0 transform vector 3))
; (.lvf vf1 (-> a2 scale))
; (cond
; ((zero? (-> t0 scale w))
; (.mul.x.vf vf2 vf2 vf1)
; (.mul.y.vf vf3 vf3 vf1)
; (.mul.z.vf vf4 vf4 vf1)
; ;; the same
; (.matrix*! acc (vf11 vf12 vf13 vf14) (vf2 vf3 vf4 (vf15 vf15 vf15 vf0)) (vf7 vf8 vf9 vf10))
; (.svf (-> a2 transform vector 0) vf11)
; (.svf (-> a2 transform vector 1) vf12)
; (.svf (-> a2 transform vector 2) vf13)
; (.svf (-> a2 transform vector 3) vf14)
; )
; (else
; (.mul.x.vf vf2 vf2 vf1)
; (.mul.y.vf vf3 vf3 vf1)
; (.mul.z.vf vf4 vf4 vf1)
; (.mov t1 (/ 1.0 (-> t0 scale x)))
; (.mov t2 (/ 1.0 (-> t0 scale y)))
; (.mov t3 (/ 1.0 (-> t0 scale z)))
; (.pextlw t1 t1 t2)
; (.pcpyld t1 t1 t3)
; (.mov vf16 t1)
; (.mul.vf vf2 vf2 vf16)
; (.mul.vf vf3 vf3 vf16)
; (.mul.vf vf4 vf4 vf16)
; ;; the same
; (.matrix*! acc (vf11 vf12 vf13 vf14) (vf2 vf3 vf4 (vf15 vf15 vf15 vf0)) (vf7 vf8 vf9 vf10))
; (.svf (-> a2 transform vector 0) vf11)
; (.svf (-> a2 transform vector 1) vf12)
; (.svf (-> a2 transform vector 2) vf13)
; (.svf (-> a2 transform vector 3) vf14)
; )
; )
; )
; )
; )
; (defun clear-frame-accumulator ((arg0 (inline-array vector)))
; ;; TODO
; (with-sp
; (.sub sp 16)
; (nop!)
; (nop!)
; (nop!)
; (nop!)
; (nop!)
; (nop!)
; (nop!)
; (nop!)
; (.add sp 16)
; )
; )
(define-extern decompress-fixed-data-to-accumulator (function none))
(define-extern decompress-frame-data-to-accumulator (function none))
(define-extern decompress-frame-data-pair-to-accumulator (function none))
;; ERROR: function was not converted to expressions. Cannot decompile.
;; ERROR: function was not converted to expressions. Cannot decompile.
;; ERROR: function was not converted to expressions. Cannot decompile.
(defun make-joint-jump-tables ()
#|
#x3ee6b6f9, // = 9 ^ 1055307504
#x3ee6b6ff, // = 15 ^ 1055307504
#x3ee6b6e2, // = 18 ^ 1055307504
#x3ee6b6e4, // = 20 ^ 1055307504
#x3ee6b6e5, // = 21 ^ 1055307504
#x3ee6b6eb, // = 27 ^ 1055307504
#x3ee6b6ee, // = 30 ^ 1055307504
#x3ee6b6f6, // = 6 ^ 1055307504
#x3ee6b6fc, // = 12 ^ 1055307504
#x3ee6b6ff, // = 15 ^ 1055307504
#x3ee6b6e3, // = 19 ^ 1055307504
#x3ee6b6e4, // = 20 ^ 1055307504
#x3ee6b6e8, // = 24 ^ 1055307504
#x3ee6b6eb, // = 27 ^ 1055307504
#x3ee6b6ef, // = 31 ^ 1055307504
#x3ee6b6f6, // = 6 ^ 1055307504
|#
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 0)
(the-as (function none) (+ 0 #x3ee6b6f9)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 1)
(the-as (function none) (+ 0 #x3ee6b6ff)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 2)
(the-as (function none) (+ 0 #x3ee6b6e2)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 3)
(the-as (function none) (+ 0 #x3ee6b6e4)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 4)
(the-as (function none) (+ 0 #x3ee6b6e5)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 5)
(the-as (function none) (+ 0 #x3ee6b6eb)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 6)
(the-as (function none) (+ 0 #x3ee6b6ee)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 7)
(the-as (function none) (+ 0 #x3ee6b6f6)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 8)
(the-as (function none) (+ 0 #x3ee6b6fc)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 9)
(the-as (function none) (+ 0 #x3ee6b6ff)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 10)
(the-as (function none) (+ 0 #x3ee6b6e3)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 11)
(the-as (function none) (+ 0 #x3ee6b6e4)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 12)
(the-as (function none) (+ 0 #x3ee6b6e8)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 13)
(the-as (function none) (+ 0 #x3ee6b6eb)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 14)
(the-as (function none) (+ 0 #x3ee6b6ef)))
(set! (-> (scratchpad-object terrain-context) work foreground joint-work fix-jmp-table 15)
(the-as (function none) (+ 0 #x3ee6b6f6)))
(let ((arr (new 'static
'array
uint32
16
#x7b2191b ;; = 6 ^ 129112349
#x7b21914 ;; = 9 ^ 129112349
#x7b21916 ;; = 11 ^ 129112349
#x7b21913 ;; = 14 ^ 129112349
#x7b21909 ;; = 20 ^ 129112349
#x7b21908 ;; = 21 ^ 129112349
#x7b2190a ;; = 23 ^ 129112349
#x7b21907 ;; = 26 ^ 129112349
#x7b2191b ;; = 6 ^ 129112349
#x7b21917 ;; = 10 ^ 129112349
#x7b21916 ;; = 11 ^ 129112349
#x7b2190c ;; = 17 ^ 129112349
#x7b21909 ;; = 20 ^ 129112349
#x7b2190b ;; = 22 ^ 129112349
#x7b2190a ;; = 23 ^ 129112349
#x7b21900 ;; = 29 ^ 129112349
)))
(dotimes (i 16)
(set! (-> (scratchpad-object terrain-context) work foreground joint-work frm-jmp-table i)
(the-as (function none) (-> arr i)))))
(let ((arr (new 'static
'array
uint32
16
#x4d7666df ;; = 6 ^ 1299605209
#x4d7666d0 ;; = 9 ^ 1299605209
#x4d7666d2 ;; = 11 ^ 1299605209
#x4d7666d7 ;; = 14 ^ 1299605209
#x4d7666cd ;; = 20 ^ 1299605209
#x4d7666cc ;; = 21 ^ 1299605209
#x4d7666ce ;; = 23 ^ 1299605209
#x4d7666c3 ;; = 26 ^ 1299605209
#x4d7666df ;; = 6 ^ 1299605209
#x4d7666d3 ;; = 10 ^ 1299605209
#x4d7666d2 ;; = 11 ^ 1299605209
#x4d7666c8 ;; = 17 ^ 1299605209
#x4d7666cd ;; = 20 ^ 1299605209
#x4d7666cf ;; = 22 ^ 1299605209
#x4d7666ce ;; = 23 ^ 1299605209
#x4d7666c4 ;; = 29 ^ 1299605209
)))
(dotimes (i 16)
(set! (-> (scratchpad-object terrain-context) work foreground joint-work pair-jmp-table i)
(the-as (function none) (-> arr i)))))
0)
; (defun calc-animation-from-spr ((arg0 (inline-array vector)) (arg1 int))
; (declare (asm-func object)
; (allow-saved-regs) ;; very dangerous!
; )
; (with-sp
; ;; useless possibly leftover reg move here
; (rlet (
; (s0 :reg rbx)
; (s1 :reg rbp)
; (s2 :reg r10)
; (s3 :reg r11)
; (s4 :reg r12)
; (s6 :reg r13)
; )
; ;(.sub sp -16)
; (let ((joint-num arg1))
; )
; ;(.add sp 16)
; )
; )
; (.ret)
; )
(def-mips2c calc-animation-from-spr (function (inline-array vector) int none))
(defun create-interpolated-joint-animation-frame ((arg0 (inline-array vector)) (arg1 int) (arg2 process-drawable))
(cond
(*use-new-decompressor* (new-joint-decompressor (the joint-anim-frame arg0) arg1 (-> arg2 skel)))
(else (flatten-joint-control-to-spr (-> arg2 skel)) (make-joint-jump-tables) (calc-animation-from-spr arg0 arg1)))
0)