jak-project/goal_src/engine/math/vector.gc
Tyler Wilding b75a64fc29
(init-vf0-vector) to make vector code a bit more readable (#494)
* decomp: Use a macro for loading VF0 (maybe should be in goal-lib.gc?)

* update references

* lint: format

* delete now unused file
2021-05-16 13:49:24 -04:00

1318 lines
36 KiB
Common Lisp

;;-*-Lisp-*-
(in-package goal)
;; name: vector.gc
;; name in dgo: vector
;; dgos: GAME, ENGINE
(defun vector-cross! ((arg0 vector) (arg1 vector) (arg2 vector))
"Compute the cross product. The w component is set to junk."
(rlet ((acc :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(.lvf vf1 (&-> arg1 quad))
(.lvf vf2 (&-> arg2 quad))
(.outer.product.vf vf3 vf1 vf2)
(.svf (&-> arg0 quad) vf3)
arg0
)
)
(defun vector+float! ((arg0 vector) (arg1 vector) (arg2 float))
"Add float to each component of vector. The w component is set to 1"
(rlet ((vf0 :class vf)
(vf4 :class vf)
(vf5 :class vf)
(vf6 :class vf)
)
(init-vf0-vector)
(.mov vf6 arg2)
(.lvf vf4 (&-> arg1 quad))
(.add.x.vf vf5 vf0 vf0 :mask #b1000)
(.add.x.vf vf5 vf4 vf6 :mask #b111)
(.svf (&-> arg0 quad) vf5)
arg0
)
)
(defun vector*! ((arg0 vector) (arg1 vector) (arg2 vector))
"Elementwise product. Set w = 1"
(rlet ((vf0 :class vf)
(vf4 :class vf)
(vf5 :class vf)
(vf6 :class vf)
)
(init-vf0-vector)
(.lvf vf4 (&-> arg1 quad))
(.lvf vf5 (&-> arg2 quad))
(.add.x.vf vf6 vf0 vf0 :mask #b1000)
(.mul.vf vf6 vf4 vf5 :mask #b111)
(.svf (&-> arg0 quad) vf6)
arg0
)
)
(defun vector+*! ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 float))
"set arg0 = arg1 + (arg3 * arg2). The w component will be set to 1"
(rlet ((acc :class vf)
(vf0 :class vf)
(vf4 :class vf)
(vf5 :class vf)
(vf6 :class vf)
(vf7 :class vf)
)
(init-vf0-vector)
(.mov vf7 arg3)
(.lvf vf5 (&-> arg2 quad))
(.lvf vf4 (&-> arg1 quad))
(.add.x.vf vf6 vf0 vf0 :mask #b1000)
(.mul.x.vf acc vf5 vf7 :mask #b111)
;; acts as just an add.
(.add.mul.w.vf vf6 vf4 vf0 acc :mask #b111)
(.svf (&-> arg0 quad) vf6)
arg0
)
)
(defun vector-*! ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 float))
"Set arg0 = arg1 - (arg3 * arg2). The w component will be set to 1."
(rlet ((acc :class vf)
(vf0 :class vf)
(vf4 :class vf)
(vf5 :class vf)
(vf6 :class vf)
(vf7 :class vf)
)
(init-vf0-vector)
(.mov vf7 arg3)
(.lvf vf5 (&-> arg2 quad))
(.lvf vf4 (&-> arg1 quad))
(.add.x.vf vf6 vf0 vf0 :mask #b1000)
(.mul.w.vf acc vf4 vf0 :mask #b111)
(.sub.mul.x.vf vf6 vf5 vf7 acc :mask #b111)
(.svf (&-> arg0 quad) vf6)
arg0
)
)
(defun vector/! ((arg0 vector) (arg1 vector) (arg2 vector))
"Set arg0 = arg1 / arg2. The w component will be set to 1.
The implementation is kind of crazy."
(rlet ((Q :class vf)
(vf0 :class vf)
(vf4 :class vf)
(vf5 :class vf)
(vf6 :class vf)
(vf7 :class vf)
)
(init-vf0-vector)
(.lvf vf5 (&-> arg2 quad))
;; get started on the first divide ASAP.
;; do this before loading the second value.
;; q = 1 / arg2.y
(.div.vf Q vf0 vf5 :fsf #b11 :ftf #b1)
(.add.x.vf vf6 vf0 vf0 :mask #b1000)
(.lvf vf4 (&-> arg1 quad))
;; use FPU to divide x while VU0 is dividing y.
(let ((v1-0 (/ (-> arg1 data 0) (-> arg2 data 0))))
(.wait.vf)
(.mul.vf vf6 vf4 Q :mask #b10)
(.nop.vf)
(.nop.vf)
(.div.vf Q vf0 vf5 :fsf #b11 :ftf #b10)
(.mov vf7 v1-0)
)
(.add.x.vf vf6 vf0 vf7 :mask #b1)
(.wait.vf)
(.mul.vf vf6 vf4 Q :mask #b100)
(.nop.vf)
(.nop.vf)
(.svf (&-> arg0 quad) vf6)
arg0
)
)
(defun vector-float*! ((arg0 vector) (arg1 vector) (arg2 float))
"Multiply all values in a vector by arg2. Set w to 1."
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg1 quad))
(.mov vf2 arg2)
(.add.x.vf vf1 vf0 vf0 :mask #b1000)
(.mul.x.vf vf1 vf1 vf2 :mask #b111)
(.svf (&-> arg0 quad) vf1)
arg0
)
)
(defun vector-average! ((arg0 vector) (arg1 vector) (arg2 vector))
"Set arg0 to the average of arg1 and arg2. Set w to 1."
(rlet ((acc :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
)
(init-vf0-vector)
(let ((v1-0 #x3f000000))
(.lvf vf1 (&-> arg1 quad))
(.lvf vf2 (&-> arg2 quad))
(.mov vf3 v1-0)
)
(.add.x.vf vf4 vf0 vf0 :mask #b1000)
(.mul.x.vf acc vf1 vf3)
(.add.mul.x.vf vf4 vf2 vf3 acc :mask #b111)
(.svf (&-> arg0 quad) vf4)
arg0
)
)
(defun vector+float*! ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 float))
"Set arg0 = arg1 + (arg2 * arg3). The w component will be set to 1.
Is this different at all from vector+*! ? The implementation is slightly different
but I think it comes out to the same thing."
(rlet ((acc :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
)
(init-vf0-vector)
(.lvf vf2 (&-> arg2 quad))
(.lvf vf1 (&-> arg1 quad))
(.mov vf3 arg3)
(.add.x.vf vf4 vf0 vf0 :mask #b1000)
(.mul.x.vf acc vf2 vf3)
(.add.mul.w.vf vf4 vf1 vf0 acc :mask #b111)
(.svf (&-> arg0 quad) vf4)
arg0
)
)
(defun vector--float*! ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 float))
"Set arg0 = arg1 - (arg2 * arg3). The w component will be set to 1
Is this different from vector-*!"
(rlet ((acc :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
)
(init-vf0-vector)
(.lvf vf2 (&-> arg2 quad))
(.lvf vf1 (&-> arg1 quad))
(.mov vf3 arg3)
(.add.x.vf vf4 vf0 vf0 :mask #b1000)
(.mul.w.vf acc vf1 vf0)
(.sub.mul.x.vf vf4 vf2 vf3 acc :mask #b111)
(.svf (&-> arg0 quad) vf4)
arg0
)
)
(defun vector-float/! ((arg0 vector) (arg1 vector) (arg2 float))
"Divide all components by arg2. The w component will be set to 1."
(rlet ((Q :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf3 :class vf)
(vf4 :class vf)
)
(init-vf0-vector)
(.mov vf3 arg2)
(.div.vf Q vf0 vf3 :fsf #b11 :ftf #b0)
(.lvf vf1 (&-> arg1 quad))
(.add.x.vf vf4 vf0 vf0 :mask #b1000)
(.wait.vf)
(.mul.vf vf4 vf1 Q :mask #b111)
(.nop.vf)
(.nop.vf)
(.svf (&-> arg0 quad) vf4)
arg0
)
)
(defun vector-negate! ((arg0 vector) (arg1 vector))
"Negate xyz, set w to 1"
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf4 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg1 quad))
(.sub.vf vf4 vf0 vf1 :mask #b111)
(.add.x.vf vf4 vf0 vf0 :mask #b1000)
(.svf (&-> arg0 quad) vf4)
arg0
)
)
(defun vector-negate-in-place! ((arg0 vector))
"Negate xyz. Doesn't touch w."
(rlet ((vf0 :class vf)
(vf1 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg0 quad))
(.sub.vf vf1 vf0 vf1 :mask #b111)
(.svf (&-> arg0 quad) vf1)
arg0
)
)
(defun vector= ((arg0 vector) (arg1 vector))
"Are the two vectors equal? Does not compare the w component.
The implementation is cool."
;; (label L91)
;; (set! v0-0 #t)
;; (set! v1-0 #xffff)
(let* ((v1-0 #xffff)
;; (set! a0-1 (l.q a0-0))
(a0-1 (-> arg0 quad))
;; (set! v1-1 (sll v1-0 48))
(v1-1 (shl v1-0 48))
;; (set! a1-1 (l.q a1-0))
(a1-1 (-> arg1 quad))
(a0-2 (the uint128 0))
(r0 (the uint128 0))
)
;; (.pceqw a0-2 a0-1 a1-1)
(.pceqw a0-2 a0-1 a1-1)
;; (.ppach a0-3 r0-0 a0-2)
(.ppach a0-2 r0 a0-2)
;; (set! v1-2 (logior a0-3 v1-1))
(set! v1-1 (logior (the int a0-2) v1-1))
;; (set! v1-3 (+ v1-2 1))
;; will overflow the 64-bit integer if xyz is equal.
(set! v1-1 (+ v1-1 1))
(zero? v1-1)
)
;; (b! (zero? v1-3) L92 (nop!))
;; (set! v0-0 #f)
;; (label L92)
;; (ret-value v0-0)
)
(defun vector-delta ((arg0 vector) (arg1 vector))
"Sum of the elementwise absolute value of differences"
(local-vars (v0-0 float))
(rlet ((acc :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg0 quad))
(.lvf vf2 (&-> arg1 quad))
(.sub.vf vf1 vf2 vf1)
(.abs.vf vf1 vf1)
;; put abs.x in acc.w
(.mul.x.vf acc vf0 vf1 :mask #b1000)
;; add abs.y
(.add.mul.y.vf acc vf0 vf1 acc :mask #b1000)
;; add abs.z
(.add.mul.z.vf vf3 vf0 vf1 acc :mask #b1000)
;; set acc.x = acc.w
(.add.w.vf vf3 vf0 vf3 :mask #b1)
(.mov v0-0 vf3)
v0-0
)
)
(defun vector-seek! ((arg0 vector) (arg1 vector) (arg2 float))
"Seek arg0 toward arg1. The arg0 is both read and written.
arg2 is saturated to (0, 1)"
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
(vf5 :class vf)
)
(init-vf0-vector)
(.mov vf4 arg2)
(.lvf vf1 (&-> arg1 quad))
(.lvf vf2 (&-> arg0 quad))
(.add.x.vf vf1 vf0 vf0 :mask #b1000)
(.sub.x.vf vf5 vf0 vf4 :mask #b1)
(.sub.vf vf3 vf1 vf2 :mask #b111)
(.min.x.vf vf3 vf3 vf4 :mask #b111)
(.max.x.vf vf3 vf3 vf5 :mask #b111)
(.add.vf vf1 vf2 vf3 :mask #b111)
(.svf (&-> arg0 quad) vf1)
arg0
)
)
(defun vector-seek-2d-xz-smooth! ((vec vector) (target vector) (max-step float) (alpha float))
"Smoothly seek vec's x and z components toward target.
The step always points toward the target and has length (dist * alpha)
If the step is longer than max-step, the step is projected onto a circle of radius max-step.
Doesn't touch y or w."
;; how much we have to go to get to the target
(let ((x-diff (- (-> target data 0) (-> vec data 0)))
(z-diff (- (-> target data 2) (-> vec data 2)))
)
;; do we have to move?
(if (or (!= x-diff 0.0) (!= z-diff 0.0))
;; if so, scale by alpha,
(let* ((x-step (* x-diff alpha))
(z-step (* z-diff alpha))
;; and get the length of this step
(step-len (sqrtf (+ (* x-step x-step) (* z-step z-step))))
)
(cond
((>= max-step step-len)
;; step is within max-step, just do it.
(+! (-> vec data 0) x-step)
(+! (-> vec data 2) z-step)
)
(else
;; not in range.
(let ((f2-6 (/ max-step step-len)))
(+! (-> vec data 0) (* f2-6 x-step))
(+! (-> vec data 2) (* f2-6 z-step))
)
)
)
)
)
)
vec
)
(defun vector-seek-2d-yz-smooth! ((vec vector) (target vector) (max-step float) (alpha float))
"Smoothly seek vec's y and z components toward target.
The step always points toward the target and has length (dist * alpha)
If the step is longer than max-step, the step is projected onto a circle of radius max-step.
Doesn't touch x or w."
(let ((y-diff (- (-> target data 1) (-> vec data 1)))
(z-diff (- (-> target data 2) (-> vec data 2)))
)
(if (or (!= y-diff 0.0) (!= z-diff 0.0))
(let* ((y-step (* y-diff alpha))
(z-step (* z-diff alpha))
(step-len (sqrtf (+ (* y-step y-step) (* z-step z-step))))
)
(cond
((>= max-step step-len)
(set! (-> vec data 1) (+ (-> vec data 1) y-step))
(let ((f0-4 (+ (-> vec data 2) z-step)))
(set! (-> vec data 2) f0-4)
)
)
(else
(let ((step-scale (/ max-step step-len)))
(set! (-> vec data 1) (+ (-> vec data 1) (* step-scale y-step)))
(let ((f0-6 (+ (-> vec data 2) (* step-scale z-step))))
(set! (-> vec data 2) f0-6)
)
)
)
)
)
)
)
vec
)
(defun vector-seek-3d-smooth! ((vec vector) (target vector) (max-step float) (alpha float))
"Smoothly seek vec's x, y, and z components toward target.
The step always points toward the target and has length (dist * alpha)
If the step is longer than max-step, the step is projected onto a circle of radius max-step.
Doesn't touch w."
(let ((x-diff (- (-> target data 0) (-> vec data 0)))
(y-diff (- (-> target data 1) (-> vec data 1)))
(z-diff (- (-> target data 2) (-> vec data 2)))
)
(if (or (!= x-diff 0.0) (!= y-diff 0.0) (!= z-diff 0.0))
(let* ((x-step (* x-diff alpha))
(y-step (* y-diff alpha))
(z-step (* z-diff alpha))
(step-len (sqrtf (+ (+ (* x-step x-step) (* y-step y-step)) (* z-step z-step))))
)
(cond
((>= max-step step-len)
(set! (-> vec data 0) (+ (-> vec data 0) x-step))
(set! (-> vec data 1) (+ (-> vec data 1) y-step))
(let ((f0-5 (+ (-> vec data 2) z-step)))
(set! (-> vec data 2) f0-5)
)
)
(else
(let ((step-scale (/ max-step step-len)))
(set! (-> vec data 0) (+ (-> vec data 0) (* step-scale x-step)))
(set! (-> vec data 1) (+ (-> vec data 1) (* step-scale y-step)))
(let ((f0-7 (+ (-> vec data 2) (* step-scale z-step))))
(set! (-> vec data 2) f0-7)
)
)
)
)
)
)
)
vec
)
(defun seek-with-smooth ((value float) (target float) (max-step float) (alpha float) (deadband float))
"Move value closer to target.
If we are within deadband, just go straight to target.
If not, try to go alpha*err. If that is a larger step than max-step, limit to max-step"
(let ((diff (- target value)))
(if (>= deadband (fabs diff))
target
(let ((step (* diff alpha)))
(let ((min-step (- max-step)))
(cond
((< step min-step)
(set! step min-step)
)
((< max-step step)
(set! step max-step)
)
)
)
(+ step value)
)
)
)
)
(defun vector-identity! ((arg0 vector))
"Set arg0 to 1, 1, 1, 1"
(set! (-> arg0 data 0) 1.0)
(set! (-> arg0 data 1) 1.0)
(set! (-> arg0 data 2) 1.0)
(set! (-> arg0 data 3) 1.0)
arg0
)
(defun vector-seconds ((arg0 vector) (arg1 vector))
"Convert from actual seconds to the seconds unit."
(set! (-> arg0 data 0) (seconds (-> arg1 data 0)))
(set! (-> arg0 data 1) (seconds (-> arg1 data 1)))
(set! (-> arg0 data 2) (seconds (-> arg1 data 2)))
arg0
)
(defun vector-seconds! ((arg0 vector))
"Convert from actual seconds to seconds, in place"
(set! (-> arg0 data 0) (seconds (-> arg0 data 0)))
(set! (-> arg0 data 1) (seconds (-> arg0 data 1)))
(set! (-> arg0 data 2) (seconds (-> arg0 data 2)))
arg0
)
(defun vector-v! ((arg0 vector))
"Convert a velocity to a displacement per frame. The velocity should be in X/actual_second"
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
)
(init-vf0-vector)
(let ((v1-0 arg0))
(let ((a1-0 arg0)
(f0-0 (-> *display* seconds-per-frame))
)
(.lvf vf1 (&-> a1-0 quad))
(let ((a1-1 f0-0))
(.mov vf2 a1-1)
)
)
(.add.x.vf vf1 vf0 vf0 :mask #b1000)
(.mul.x.vf vf1 vf1 vf2 :mask #b111)
(.svf (&-> v1-0 quad) vf1)
)
arg0
)
)
(defun vector-v+! ((result vector) (position vector) (velocity vector))
"Euler forward step, using the current display time settings"
(vector+float*! result position velocity (-> *display* seconds-per-frame))
result
)
(defun vector-v*float+! ((result vector) (position vector) (velocity vector) (velocity-scale float))
"Euler forward step, scaling velocity by velocity-scale"
(vector+float*! result position velocity (* velocity-scale (-> *display* seconds-per-frame)))
result
)
(defun vector-v++! ((position vector) (velocity vector))
"Update position in place, using display's current timing"
(vector+float*! position position velocity (-> *display* seconds-per-frame))
position
)
(defun vector-v*float! ((delta-p vector) (velocity vector) (scale float))
"Go from velocity to delta-p per frame, scaling by scale"
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
)
(init-vf0-vector)
(let ((v0-0 delta-p))
(let ((v1-0 velocity)
(f0-1 (* scale (-> *display* seconds-per-frame)))
)
(.lvf vf1 (&-> v1-0 quad))
(let ((v1-1 f0-1))
(.mov vf2 v1-1)
)
)
(.add.x.vf vf1 vf0 vf0 :mask #b1000)
(.mul.x.vf vf1 vf1 vf2 :mask #b111)
(.svf (&-> v0-0 quad) vf1)
v0-0
)
)
)
(defun vector-v*float++! ((position vector) (velocity vector) (scale float))
"update position with given velocity, scaled by scale."
(vector+float*! position position velocity (* scale (-> *display* seconds-per-frame)))
position
)
(defun vector-to-ups! ((arg0 vector) (arg1 vector))
"Go from units per frame to units per second?"
(local-vars (at-0 int))
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg1 quad))
(let ((f0-0 (-> *display* frames-per-second)))
(.mov at-0 f0-0)
)
(.mov vf2 at-0)
(.mov.vf vf1 vf0 :mask #b1000)
(.mul.x.vf vf1 vf1 vf2 :mask #b111)
(.svf (&-> arg0 quad) vf1)
arg0
)
)
(defun vector-from-ups! ((arg0 vector) (arg1 vector))
"Go from units per second to units per frame?"
(local-vars (at-0 int))
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg1 quad))
(let ((f0-0 (-> *display* seconds-per-frame)))
(.mov at-0 f0-0)
)
(.mov vf2 at-0)
(.mov.vf vf1 vf0 :mask #b1000)
(.mul.x.vf vf1 vf1 vf2 :mask #b111)
(.svf (&-> arg0 quad) vf1)
arg0
)
)
(defun vector-length ((arg0 vector))
"Get the length of the xyz part."
(local-vars (v0-0 float))
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf1 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg0 quad))
(.mul.vf vf1 vf1 vf1)
(.mul.x.vf acc vf0 vf1 :mask #b1000)
(.add.mul.y.vf acc vf0 vf1 acc :mask #b1000)
(.add.mul.z.vf vf1 vf0 vf1 acc :mask #b1000)
(.sqrt.vf Q vf1 :ftf #b11)
(.add.w.vf vf1 vf0 vf0 :mask #b1)
(.wait.vf)
(.mul.vf vf1 vf1 Q :mask #b1)
(.nop.vf)
(.nop.vf)
(.mov v0-0 vf1)
v0-0
)
)
(defun vector-length-squared ((arg0 vector))
"Get the squared length of the xyz part."
(local-vars (v0-0 float))
(rlet ((acc :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg0 quad))
(.add.w.vf vf2 vf0 vf0 :mask #b1)
(.mul.vf vf1 vf1 vf1)
(.mul.x.vf acc vf2 vf1 :mask #b1)
(.add.mul.y.vf acc vf2 vf1 acc :mask #b1)
(.add.mul.z.vf vf1 vf2 vf1 acc :mask #b1)
(.mov v0-0 vf1)
v0-0
)
)
(defun vector-xz-length-squared ((arg0 vector))
"Get the length of the xz part, squared."
(+ (* (-> arg0 data 0) (-> arg0 data 0))
(* (-> arg0 data 2) (-> arg0 data 2))
)
)
(defun vector-xz-length ((arg0 vector))
"Get the length of the xz part, squared"
(sqrtf (+ (* (-> arg0 data 0) (-> arg0 data 0))
(* (-> arg0 data 2) (-> arg0 data 2))
)
)
)
(defun vector-vector-distance ((arg0 vector) (arg1 vector))
"Subtract the xyz parts and get the norm"
(local-vars (v0-0 float))
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(.lvf vf2 (&-> arg0 quad))
(.lvf vf3 (&-> arg1 quad))
(.sub.vf vf1 vf3 vf2)
(.mul.vf vf1 vf1 vf1)
(.mul.x.vf acc vf0 vf1 :mask #b1000)
(.add.mul.y.vf acc vf0 vf1 acc :mask #b1000)
(.add.mul.z.vf vf1 vf0 vf1 acc :mask #b1000)
(.sqrt.vf Q vf1 :ftf #b11)
(.add.w.vf vf1 vf0 vf0 :mask #b1)
(.wait.vf)
(.mul.vf vf1 vf1 Q :mask #b1)
(.nop.vf)
(.nop.vf)
(.mov v0-0 vf1)
v0-0
)
)
(defun vector-vector-distance-squared ((arg0 vector) (arg1 vector))
"Squared norm of the difference of the xyz parts"
(local-vars (v0-0 float))
(rlet ((vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(.lvf vf2 (&-> arg0 quad))
(.lvf vf3 (&-> arg1 quad))
(.sub.vf vf1 vf3 vf2)
(.mul.vf vf1 vf1 vf1)
(.add.y.vf vf1 vf1 vf1 :mask #b1)
(.add.z.vf vf1 vf1 vf1 :mask #b1)
(.mov v0-0 vf1)
v0-0
)
)
(defun vector-vector-xz-distance ((arg0 vector) (arg1 vector))
"Distance on the xz plane"
(local-vars (v0-0 float))
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(.lvf vf2 (&-> arg0 quad))
(.lvf vf3 (&-> arg1 quad))
(.sub.vf vf1 vf3 vf2)
(.mul.vf vf1 vf1 vf1)
(.mul.x.vf acc vf0 vf1 :mask #b1000)
(.add.mul.z.vf vf1 vf0 vf1 acc :mask #b1000)
(.sqrt.vf Q vf1 :ftf #b11)
(.add.w.vf vf1 vf0 vf0 :mask #b1)
(.wait.vf)
(.mul.vf vf1 vf1 Q :mask #b1)
(.nop.vf)
(.nop.vf)
(.mov v0-0 vf1)
v0-0
)
)
(defun vector-vector-xz-distance-squared ((arg0 vector) (arg1 vector))
"Squared distance on the xz plane"
(local-vars (v0-0 float))
(rlet ((vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(.lvf vf2 (&-> arg0 quad))
(.lvf vf3 (&-> arg1 quad))
(.sub.vf vf1 vf3 vf2)
(.mul.vf vf1 vf1 vf1)
(.add.z.vf vf1 vf1 vf1 :mask #b1)
(.mov v0-0 vf1)
v0-0
)
)
(defun vector-normalize! ((arg0 vector) (arg1 float))
"Modify arg0 in place to have length arg1 for its xyz components. The w part is not changed."
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg0 quad))
(.mul.vf vf2 vf1 vf1 :mask #b111)
(let ((v1-0 arg1))
(.mov vf3 v1-0)
)
(.mul.x.vf acc vf0 vf2 :mask #b1000)
(.add.mul.y.vf acc vf0 vf2 acc :mask #b1000)
(.add.mul.z.vf vf2 vf0 vf2 acc :mask #b1000)
(.isqrt.vf Q vf3 vf2 :fsf #b0 :ftf #b11)
(.wait.vf)
(.mul.vf vf1 vf1 Q :mask #b111)
(.nop.vf)
(.nop.vf)
(.nop.vf)
(.svf (&-> arg0 quad) vf1)
arg0
)
)
(defun vector-normalize-ret-len! ((arg0 vector) (arg1 float))
"Modify arg0 in place to have length arg1 for its xyz components.
The w part isn't changed and the _original_ length is returned."
(local-vars (v1-1 float))
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg0 quad))
(.mul.vf vf2 vf1 vf1 :mask #b111)
(let ((v1-0 arg1))
(.mov vf3 v1-0)
)
(.mul.x.vf acc vf0 vf2 :mask #b1000)
(.add.mul.y.vf acc vf0 vf2 acc :mask #b1000)
(.add.mul.z.vf vf2 vf0 vf2 acc :mask #b1000)
(.isqrt.vf Q vf3 vf2 :fsf #b0 :ftf #b11)
(.add.w.vf vf2 vf0 vf2 :mask #b1)
(.mov v1-1 vf2)
(let ((v0-0 (sqrtf v1-1)))
(.wait.vf)
(.mul.vf vf1 vf1 Q :mask #b111)
(.nop.vf)
(.nop.vf)
(.nop.vf)
(.svf (&-> arg0 quad) vf1)
v0-0
)
)
)
(defun vector-normalize-copy! ((arg0 vector) (arg1 vector) (arg2 float))
"Normalize, but not in place.
This implementation is very good compared to the vector-normalize! one.
The w component is set to 1."
(let ((f0-0 (vector-length arg1)))
(if (= f0-0 0.0)
(set! (-> arg0 quad) (-> arg1 quad))
(let ((v1-1 (/ arg2 f0-0)))
(set! (-> arg0 data 0) (* (-> arg1 data 0) v1-1))
(set! (-> arg0 data 1) (* (-> arg1 data 1) v1-1))
(let ((f0-7 (* (-> arg1 data 2) v1-1)))
(set! (-> arg0 data 2) f0-7)
)
)
)
)
(set! (-> arg0 data 3) 1.0)
arg0
)
(defun vector-xz-normalize! ((arg0 vector) (arg1 float))
"Normalize, xz components only"
(let ((f0-0 (vector-xz-length arg0)))
(if (!= f0-0 0.0)
(let ((v1-1 (/ arg1 f0-0)))
(set! (-> arg0 data 0) (* (-> arg0 data 0) v1-1))
(set! (-> arg0 data 2) (* (-> arg0 data 2) v1-1))
)
)
)
arg0
)
(defun vector-length-max! ((arg0 vector) (arg1 float))
"Make vector at most arg1 length (xyz only).
If it is larger, project onto sphere.
Doesn't touch w"
(let ((f0-0 (vector-length arg0)))
(when (not (or (= f0-0 0.0) (< f0-0 arg1)))
(set! f0-0 (/ f0-0 arg1))
(when (!= f0-0 0.0)
(set! (-> arg0 data 0) (/ (-> arg0 data 0) f0-0))
(set! (-> arg0 data 1) (/ (-> arg0 data 1) f0-0))
(set! (-> arg0 data 2) (/ (-> arg0 data 2) f0-0))
)
)
)
arg0
)
(defun vector-xz-length-max! ((arg0 vector) (arg1 float))
"Make vector at most arg1 length (xz only).
It it is larger, project onto circle.
Doesn't touch w or y"
(let ((f0-0 (vector-xz-length arg0)))
(when (not (or (= f0-0 0.0) (< f0-0 arg1)))
(set! f0-0 (/ f0-0 arg1))
(when (!= f0-0 0.0)
(set! (-> arg0 data 0) (/ (-> arg0 data 0) f0-0))
(let ((f0-1 (/ (-> arg0 data 2) f0-0)))
(set! (-> arg0 data 2) f0-1)
)
)
)
)
arg0
)
(defun vector-rotate-around-y! ((arg0 vector) (arg1 vector) (arg2 float))
"Rotate a vector around the y axis"
(let ((f26-0 (-> arg1 data 2))
(f30-0 (-> arg1 data 0))
(f28-0 (cos arg2))
(f0-0 (sin arg2))
)
(set! (-> arg0 quad) (-> arg1 quad))
(set! (-> arg0 data 2) (- (* f26-0 f28-0) (* f30-0 f0-0)))
(set! (-> arg0 data 0) (+ (* f26-0 f0-0) (* f30-0 f28-0)))
)
arg0
)
(defun rotate-y<-vector+vector ((arg0 vector) (arg1 vector))
"Get the y rotation between vectors. These should have the same length."
(atan (- (-> arg1 data 0) (-> arg0 data 0))
(- (-> arg1 data 2) (-> arg0 data 2))
)
)
(defun vector-cvt.w.s! ((arg0 vector) (arg1 vector))
"Convert float to int32. Truncate."
(rlet ((vf1 :class vf))
(.lvf vf1 (&-> arg1 quad))
(.ftoi.vf vf1 vf1)
(.svf (&-> arg0 quad) vf1)
arg0
)
)
(defun vector-cvt.s.w! ((arg0 vector) (arg1 vector))
"Convert float to int32."
(rlet ((vf1 :class vf))
(.lvf vf1 (&-> arg1 quad))
(.itof.vf vf1 vf1)
(.svf (&-> arg0 quad) vf1)
arg0
)
)
(defun rot-zxy-from-vector! ((arg0 vector) (arg1 vector))
"I think this gives you a vector of euler angles to rotate some unit vector
to arg1."
(let* ((f28-0 (-> arg1 data 2))
(f30-0 (-> arg1 data 0))
(f0-0 (atan f30-0 f28-0))
)
(set! (-> arg0 data 1) f0-0)
(let* ((f26-0 (- f0-0))
(f0-4 (- (* f28-0 (cos f26-0)) (* f30-0 (sin f26-0))))
(f0-5 (atan (- (-> arg1 data 1)) f0-4))
)
(set! (-> arg0 data 0) f0-5)
)
)
(set! (-> arg0 data 2) 0.0)
arg0
)
(defun rot-zyx-from-vector! ((arg0 vector) (arg1 vector))
"I think this gives you a vector of euler angles to rotate some unit vector
to arg1."
(let* ((f28-0 (-> arg1 data 2))
(f30-0 (- (-> arg1 data 1)))
(f0-1 (atan f30-0 f28-0))
)
(set! (-> arg0 data 0) f0-1)
(let* ((f26-0 (- f0-1))
(f0-5 (- (* f28-0 (cos f26-0)) (* f30-0 (sin f26-0))))
(f0-6 (atan (-> arg1 data 0) f0-5))
)
(set! (-> arg0 data 1) f0-6)
)
)
(set! (-> arg0 data 2) 0.0)
arg0
)
(defun vector-lerp! ((out vector) (a vector) (b vector) (alpha float))
"Linearly interpolate between two vectors. Alpha isn't clamped.
w will be set to 1."
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> a quad))
(.lvf vf2 (&-> b quad))
(.mov vf4 alpha)
(.add.x.vf vf3 vf0 vf0 :mask #b1000)
(.sub.vf vf2 vf2 vf1)
(.mul.x.vf vf2 vf2 vf4)
(.add.vf vf3 vf1 vf2 :mask #b111)
(.svf (&-> out quad) vf3)
out
)
)
(defun vector-lerp-clamp! ((out vector) (a vector) (b vector) (alpha float))
"Linearly interpolate between two vectors, clamping alpha to 0, 1
w will be set to 1."
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
)
(init-vf0-vector)
(cond
((>= 0.0 alpha)
(set! (-> out quad) (-> a quad))
)
((>= alpha 1.0)
(set! (-> out quad) (-> b quad))
)
(else
(let ((v1-2 out))
(let ((f0-2 alpha))
(.lvf vf1 (&-> a quad))
(.lvf vf2 (&-> b quad))
(let ((a1-1 f0-2))
(.mov vf4 a1-1)
)
)
(.add.x.vf vf3 vf0 vf0 :mask #b1000)
(.sub.vf vf2 vf2 vf1)
(.mul.x.vf vf2 vf2 vf4)
(.add.vf vf3 vf1 vf2 :mask #b111)
(.svf (&-> v1-2 quad) vf3)
)
)
)
out
)
)
(defun vector4-lerp! ((out vector) (a vector) (b vector) (alpha float))
"Interpolate all 4 elements of a vector. Alpha is not clamped"
(rlet ((vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
)
(.lvf vf1 (&-> a quad))
(.lvf vf2 (&-> b quad))
(.mov vf4 alpha)
(.sub.vf vf2 vf2 vf1)
(.mul.x.vf vf2 vf2 vf4)
(.add.vf vf3 vf1 vf2)
(.svf (&-> out quad) vf3)
out
)
)
(defun vector4-lerp-clamp! ((out vector) (a vector) (b vector) (alpha float))
"Interpolate all 4 elements of a vector. Alpha is clamped to [0, 1]"
(rlet ((vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
)
(cond
((>= 0.0 alpha)
(set! (-> out quad) (-> a quad))
)
((>= alpha 1.0)
(set! (-> out quad) (-> b quad))
)
(else
(let ((v1-2 out))
(let ((f0-2 alpha))
(.lvf vf1 (&-> a quad))
(.lvf vf2 (&-> b quad))
(let ((a1-1 f0-2))
(.mov vf4 a1-1)
)
)
(.sub.vf vf2 vf2 vf1)
(.mul.x.vf vf2 vf2 vf4)
(.add.vf vf3 vf1 vf2)
(.svf (&-> v1-2 quad) vf3)
)
)
)
out
)
)
(defun vector-degi ((arg0 vector) (arg1 vector))
"Convert a vector (in _rotations_) to degrees units, stored in an int.
Truncates to the nearest _rotation_.
Neither the input or output is a commonly used form.
Unsurprisingly, this strange function is never used."
(local-vars (v1-0 uint128) (v1-1 uint128))
(rlet ((vf1 :class vf))
(.lvf vf1 (&-> arg1 quad))
(.ftoi.vf vf1 vf1)
(.mov v1-0 vf1)
(.pw.sll v1-1 v1-0 16)
(set! (-> arg0 quad) (the-as uint128 v1-1))
arg0
)
)
(defun vector-degf ((arg0 vector) (arg1 vector))
"Convert a vector (in integer degree units) to floating point rotations.
Truncates to the nearest _rotation_.
Like the previous function, this is stupid and unused"
(local-vars (v1-1 uint128))
(rlet ((vf1 :class vf))
(let ((v1-0 (-> arg1 quad)))
(.pw.sra v1-1 v1-0 16)
)
(.mov vf1 v1-1)
(.itof.vf vf1 vf1)
(.svf (&-> arg0 quad) vf1)
arg0
)
)
(defun vector-degmod ((arg0 vector) (arg1 vector))
"This one is actually right. Wraps degrees units (in floats, like they should be)
to +/- half a rotation."
(local-vars (v1-0 uint128) (v1-1 uint128) (v1-2 uint128))
(rlet ((vf1 :class vf))
(.lvf vf1 (&-> arg1 quad))
(.ftoi.vf vf1 vf1)
(.mov v1-0 vf1)
(.pw.sll v1-1 v1-0 16)
(.pw.sra v1-2 v1-1 16)
(.mov vf1 v1-2)
(.itof.vf vf1 vf1)
(.svf (&-> arg0 quad) vf1)
arg0
)
)
(defun vector-deg-diff ((arg0 vector) (arg1 vector) (arg2 vector))
"Wrapped difference, degrees units. Will have the usual 16-bit accuracy issue"
(local-vars
(v0-0 float)
(v1-0 uint128)
(v1-1 uint128)
(v1-2 uint128)
(v1-3 uint128)
(a1-1 uint128)
(a1-2 uint128)
)
(rlet ((vf1 :class vf)
(vf2 :class vf)
)
(.lvf vf1 (&-> arg1 quad))
(.lvf vf2 (&-> arg2 quad))
(.ftoi.vf vf1 vf1)
(.ftoi.vf vf2 vf2)
(.mov a1-1 vf1)
(.mov v1-0 vf2)
(.pw.sll a1-2 a1-1 16)
(.pw.sll v1-1 v1-0 16)
(.psubw v1-2 a1-2 v1-1)
(.pw.sra v1-3 v1-2 16)
(.mov vf1 v1-3)
(.itof.vf vf1 vf1)
(.svf (&-> arg0 quad) vf1)
(.mov v0-0 vf1)
(none)
)
)
(defun vector-deg-lerp-clamp! ((out vector) (min-val vector) (max-val vector) (in float))
"Apply deg-lerp-clamp to the xyz components of a vector. Sets w = 1."
(cond
((>= 0.0 in)
;; there is actually something weird here where it is not possible
;; this was written like you would expect. Perhaps this is from a macro?
(let ((v1-0 out))
(set! (-> v1-0 quad) (-> min-val quad))
)
)
((>= in 1.0)
(let ((v1-1 out))
(set! (-> v1-1 quad) (-> max-val quad))
)
)
(else
(set! (-> out data 0)
(deg-lerp-clamp (-> min-val data 0) (-> max-val data 0) in)
)
(set! (-> out data 1)
(deg-lerp-clamp (-> min-val data 1) (-> max-val data 1) in)
)
(set! (-> out data 2)
(deg-lerp-clamp (-> min-val data 2) (-> max-val data 2) in)
)
(set! (-> out data 3) 1.0)
)
)
out
)
;; The weird docstrings for the next 4 functions were left behind in the game.
;; We suspect they accidentally put something before the docstring, turning it
;; into a string constant. GOAL doesn't eliminate dead code and
;; loads into registers greedily, so it decompiles into a variable assignment.
(defun vector3s-copy! ((arg0 vector) (arg1 vector))
(let ((v1-0 "Copy a vector3s"))
)
(set! (-> arg0 data 0) (-> arg1 data 0))
(set! (-> arg0 data 1) (-> arg1 data 1))
(set! (-> arg0 data 2) (-> arg1 data 2))
arg0
)
(defun vector3s+! ((arg0 vector) (arg1 vector) (arg2 vector))
(let ((v1-0 "Add 2 vectors3."))
)
(set! (-> arg0 data 0) (+ (-> arg1 data 0) (-> arg2 data 0)))
(set! (-> arg0 data 1) (+ (-> arg1 data 1) (-> arg2 data 1)))
(set! (-> arg0 data 2) (+ (-> arg1 data 2) (-> arg2 data 2)))
arg0
)
(defun vector3s*float! ((arg0 vector) (arg1 vector) (arg2 float))
(let ((v1-0 "mult vectors3 by float"))
)
(set! (-> arg0 data 0) (* (-> arg1 data 0) arg2))
(set! (-> arg0 data 1) (* (-> arg1 data 1) arg2))
(set! (-> arg0 data 2) (* (-> arg1 data 2) arg2))
arg0
)
(defun vector3s-! ((arg0 vector) (arg1 vector) (arg2 vector))
(let ((v1-0 "Subtract 2 vectors3: c = (a - b)."))
)
(set! (-> arg0 data 0) (- (-> arg1 data 0) (-> arg2 data 0)))
(set! (-> arg0 data 1) (- (-> arg1 data 1) (-> arg2 data 1)))
(set! (-> arg0 data 2) (- (-> arg1 data 2) (-> arg2 data 2)))
arg0
)
(defun spheres-overlap? ((arg0 sphere) (arg1 sphere))
"Do the spheres overlap?"
(local-vars (v1-0 float) (a0-1 float))
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> arg0 quad))
(.lvf vf2 (&-> arg1 quad))
(.sub.vf vf3 vf1 vf2 :mask #b111)
(.mul.vf vf3 vf3 vf3 :mask #b111)
(.add.w.vf vf4 vf1 vf2 :mask #b1000)
(.mul.w.vf vf4 vf4 vf4 :mask #b1000)
(.add.y.vf vf3 vf3 vf3 :mask #b1)
(.add.z.vf vf3 vf3 vf3 :mask #b1)
(.add.w.vf vf4 vf0 vf4 :mask #b1)
(.mov a0-1 vf4)
(.mov v1-0 vf3)
(>= a0-1 v1-0)
)
)
(defun sphere<-vector! ((arg0 sphere) (arg1 vector))
"Set the position of the sphere to arg1. Does not change the radius"
(let ((f0-0 (-> arg0 data 3)))
(set! (-> arg0 quad) (-> arg1 quad))
(set! (-> arg0 data 3) f0-0)
)
arg0
)
(defun sphere<-vector+r! ((arg0 sphere) (arg1 vector) (arg2 float))
"Set the position of the sphere from arg1 and the radius from arg2"
(set! (-> arg0 quad) (-> arg1 quad))
(set! (-> arg0 data 3) arg2)
arg0
)
(defun rand-vu-sphere-point! ((arg0 vector) (arg1 float))
"Get a random point on the sphere at the origin with radius arg1.
The point is on the surface of the sphere."
(let ((s4-0 arg0))
(set! (-> s4-0 data 0) (rand-vu-float-range -1.0 1.0))
(set! (-> s4-0 data 1) (rand-vu-float-range -1.0 1.0))
(set! (-> s4-0 data 2) (rand-vu-float-range -1.0 1.0))
(set! (-> s4-0 data 3) 1.0)
)
(vector-normalize! arg0 (rand-vu-float-range 0.0 arg1))
)