mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-21 07:37:45 -04:00
247 lines
7.9 KiB
Common Lisp
247 lines
7.9 KiB
Common Lisp
;;-*-Lisp-*-
|
|
(in-package goal)
|
|
|
|
;; name: collide-cache.gc
|
|
;; name in dgo: collide-cache
|
|
;; dgos: GAME, ENGINE
|
|
|
|
;; TODO this doesnt work properly due to qmfc2 bugs
|
|
(defun collide-cache-using-box-test ((arg0 vector))
|
|
(local-vars (v1-1 float))
|
|
(rlet ((acc :class vf)
|
|
(vf0 :class vf)
|
|
(vf1 :class vf)
|
|
(vf2 :class vf)
|
|
(vf3 :class vf)
|
|
)
|
|
(init-vf0-vector)
|
|
(nop!)
|
|
(.max.w.vf vf3 vf0 vf0)
|
|
(let ((v1-0 *collide-work*))
|
|
(nop!)
|
|
(.lvf vf1 (&-> arg0 quad))
|
|
(nop!)
|
|
(.lvf vf2 (&-> v1-0 collide-sphere-neg-r quad))
|
|
)
|
|
(.sub.vf vf1 vf1 vf2)
|
|
(nop!)
|
|
(.mul.vf vf1 vf1 vf1)
|
|
(nop!)
|
|
(.mul.x.vf acc vf3 vf1)
|
|
(nop!)
|
|
(.add.mul.y.vf acc vf3 vf1 acc)
|
|
(nop!)
|
|
(.add.mul.z.vf acc vf3 vf1 acc)
|
|
(nop!)
|
|
(.sub.mul.w.vf vf1 vf3 vf1 acc)
|
|
(nop!)
|
|
(.mov v1-1 vf1)
|
|
(<= (the-as int v1-1) 0)
|
|
)
|
|
)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;
|
|
;; Line Sphere Test
|
|
;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; In this mode, we collide a line of spheres.
|
|
;; The first pass sets up a non-axis-aligned bounding box in *collide-work*
|
|
;; The box is stored as an axis-aligned box, and an inv-rot to transform from world to aligned-box coordinates.
|
|
|
|
|
|
(defun collide-cache-using-line-sphere-test ((arg0 vector))
|
|
"Check if the input sphere is in the rotated bounding box volume of the current
|
|
line-sphere query."
|
|
(local-vars
|
|
(v1-1 uint128)
|
|
(v1-2 uint128)
|
|
(v1-3 uint128)
|
|
(a0-1 uint128)
|
|
(a1-2 uint128)
|
|
(a2-0 uint128)
|
|
(zero uint128)
|
|
)
|
|
(rlet ((acc :class vf)
|
|
(vf0 :class vf)
|
|
(vf1 :class vf)
|
|
(vf10 :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)
|
|
)
|
|
(init-vf0-vector)
|
|
(set! zero (the uint128 0))
|
|
(let ((a1-0 *collide-work*))
|
|
(.lvf vf5 (&-> arg0 quad))
|
|
(.lvf vf4 (&-> a1-0 inv-mat vector 3 quad))
|
|
(.lvf vf1 (&-> a1-0 inv-mat vector 0 quad))
|
|
(.mul.w.vf acc vf4 vf0)
|
|
(.lvf vf2 (&-> a1-0 inv-mat vector 1 quad))
|
|
(.add.mul.x.vf acc vf1 vf5 acc)
|
|
(.lvf vf3 (&-> a1-0 inv-mat vector 2 quad))
|
|
(.add.mul.y.vf acc vf2 vf5 acc)
|
|
(let ((v1-0 (-> a1-0 collide-box4w min quad)))
|
|
(.add.mul.z.vf vf10 vf3 vf5 acc)
|
|
(let ((a1-1 (-> a1-0 collide-box4w max quad)))
|
|
(.sub.w.vf vf6 vf10 vf5 :mask #b111)
|
|
(.add.w.vf vf7 vf10 vf5 :mask #b111)
|
|
(.ftoi.vf vf8 vf6)
|
|
(.ftoi.vf vf9 vf7)
|
|
(.mov a2-0 vf8)
|
|
(.mov a0-1 vf9)
|
|
(.pcgtw a1-2 a2-0 a1-1)
|
|
)
|
|
(.pcgtw v1-1 v1-0 a0-1)
|
|
)
|
|
)
|
|
(.por v1-2 a1-2 v1-1)
|
|
(.ppach v1-3 zero v1-2)
|
|
(let ((v1-4 (shl (the-as int v1-3) 16)))
|
|
(nop!)
|
|
(zero? v1-4)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
(defun make-collide-list-using-line-sphere-inst-test ((arg0 collide-fragment) (arg1 instance-tie))
|
|
"Check if a collide-fragment at a given instance is in the rotated bounding box volume
|
|
of the current line-sphere query."
|
|
(local-vars (v1-1 uint128) (v1-2 uint128) (v1-3 uint128) (v1-4 uint128) (a1-2 uint128) (a2-1 uint128)
|
|
(a3-1 uint128) (a3-3 uint128) (a3-4 uint128) (t0-1 uint128) (t0-2 uint128) (t1-0 uint128) (t2-1 uint128)
|
|
(t2-2 uint128) (zero uint128))
|
|
(rlet ((acc :class vf) (vf0 :class vf) (vf1 :class vf) (vf10 :class vf) (vf11 :class vf) (vf12 :class vf)
|
|
(vf13 :class vf) (vf14 :class vf) (vf15 :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))
|
|
(init-vf0-vector)
|
|
(set! zero (the uint128 0))
|
|
(let ((v1-0 *collide-work*))
|
|
(let ((a2-0 (-> arg1 max-scale)))
|
|
(let ((a3-0 (the-as uint128 (-> arg1 origin vector4h 3 long))))
|
|
(let ((t2-0 (the-as uint128 (-> arg1 origin vector4h 0 long))))
|
|
(.pextlh a3-1 a3-0 zero)
|
|
(let ((t0-0 (the-as uint128 (-> arg1 origin vector4h 1 long))))
|
|
(.pw.sra t1-0 a3-1 10)
|
|
(let ((a3-2 (the-as uint128 (-> arg1 origin vector4h 2 long))))
|
|
(.pextlh t2-1 t2-0 zero)
|
|
(.pw.sra t2-2 t2-1 16)
|
|
(.pextlh t0-1 t0-0 zero)
|
|
(.mov vf4 t1-0)
|
|
(.pw.sra t0-2 t0-1 16)
|
|
(.mov vf1 t2-2)
|
|
(.pextlh a3-3 a3-2 zero)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(.mov vf2 t0-2)
|
|
(.pw.sra a3-4 a3-3 16)
|
|
(.lvf vf5 (&-> arg1 bsphere quad))
|
|
(.mov vf3 a3-4)
|
|
(.mov vf6 a2-0)
|
|
)
|
|
(.itof.vf vf4 vf4)
|
|
(vitof12.xyzw vf1 vf1)
|
|
(vitof12.xyzw vf2 vf2)
|
|
(vitof12.xyzw vf3 vf3)
|
|
(.add.vf vf4 vf4 vf5 :mask #b111)
|
|
(.lvf vf5 (&-> arg0 bsphere quad))
|
|
(vitof12.xyzw vf6 vf6)
|
|
(.mul.x.vf acc vf1 vf5)
|
|
(.add.mul.y.vf acc vf2 vf5 acc)
|
|
(.add.mul.z.vf acc vf3 vf5 acc)
|
|
(.add.mul.w.vf vf11 vf4 vf0 acc)
|
|
(.lvf vf7 (&-> v1-0 inv-mat vector 0 quad))
|
|
(.lvf vf8 (&-> v1-0 inv-mat vector 1 quad))
|
|
(.lvf vf9 (&-> v1-0 inv-mat vector 2 quad))
|
|
(.lvf vf10 (&-> v1-0 inv-mat vector 3 quad))
|
|
(.mul.x.vf acc vf7 vf11)
|
|
(let ((a0-1 (-> v1-0 collide-box4w min quad)))
|
|
(.add.mul.y.vf acc vf8 vf11 acc)
|
|
(let ((a1-1 (-> v1-0 collide-box4w max quad)))
|
|
(.add.mul.z.vf acc vf9 vf11 acc)
|
|
(.add.mul.w.vf vf11 vf10 vf0 acc)
|
|
(.mul.w.vf vf15 vf6 vf5 :mask #b1)
|
|
(.add.x.vf vf12 vf11 vf15 :mask #b111)
|
|
(.sub.x.vf vf11 vf11 vf15 :mask #b111)
|
|
(.ftoi.vf vf14 vf12)
|
|
(.ftoi.vf vf13 vf11)
|
|
(.mov v1-1 vf14)
|
|
(.mov a2-1 vf13)
|
|
(.pcgtw a1-2 a2-1 a1-1)
|
|
)
|
|
(.pcgtw v1-2 a0-1 v1-1)
|
|
)
|
|
)
|
|
(.por v1-3 a1-2 v1-2)
|
|
(.ppach v1-4 zero v1-3)
|
|
(let ((v1-5 (shl (the-as int v1-4) 16)))
|
|
(nop!)
|
|
(zero? v1-5)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
(defmethod collide-ray collide-fragment ((obj collide-fragment) (arg0 int) (arg1 collide-list))
|
|
"Inline-array function to do line-sphere with non-instanced fragments.
|
|
If the bsphere of the mesh is in the non-aligned bounding box, the mesh will be added
|
|
to the given collide-list.
|
|
Note: collide-probe is the faster implementation of this."
|
|
*collide-work*
|
|
|
|
;; just iterate over all and check their bsphere.
|
|
(dotimes (s3-0 arg0)
|
|
(when (collide-cache-using-line-sphere-test (-> obj bsphere))
|
|
(let ((v1-5 (-> arg1 items (-> arg1 num-items))))
|
|
(set! (-> v1-5 mesh) (-> obj mesh))
|
|
(set! (-> v1-5 inst) #f) ;; non-instanced.
|
|
)
|
|
(+! (-> arg1 num-items) 1)
|
|
)
|
|
(&+! obj 32)
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
|
|
(defmethod collide-ray instance-tie ((obj instance-tie) (arg0 int) (arg1 collide-list))
|
|
"Inline-array function to do line-sphere with TIE instances.
|
|
If the bsphere of the mesh is in the non-aligned bounding box, the mesh will be added
|
|
to the given collide-list.
|
|
Note: collide-probe is the faster implementation of this."
|
|
|
|
;; loop over instance-ties
|
|
(dotimes (s3-0 arg0)
|
|
;; first check the instance-tie's bsphere
|
|
(when (and (zero? (logand (-> obj flags) 1)) (collide-cache-using-line-sphere-test (-> obj bsphere)))
|
|
;; now, find the collide-frag
|
|
(let ((s2-0 (-> obj bucket-ptr collide-frag)))
|
|
(when (nonzero? s2-0)
|
|
(let ((s1-0 (the-as object (-> s2-0 data))))
|
|
;; and check each mesh in the collide-frag
|
|
(dotimes (s0-0 (-> s2-0 length))
|
|
(when (make-collide-list-using-line-sphere-inst-test (the-as collide-fragment s1-0) obj)
|
|
(let ((v1-10 (-> arg1 items (-> arg1 num-items))))
|
|
(set! (-> v1-10 mesh) (-> (the-as collide-fragment s1-0) mesh))
|
|
(set! (-> v1-10 inst) obj)
|
|
)
|
|
(+! (-> arg1 num-items) 1)
|
|
)
|
|
(set! s1-0 (-> (the-as (inline-array collide-fragment) s1-0) 1))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(&+! obj 64)
|
|
)
|
|
0
|
|
(none)
|
|
) |