mirror of
https://github.com/open-goal/jak-project
synced 2026-08-10 03:06:18 -04:00
95366d21df
* wip * temp * temp2 * first part of log macros * more log macros * logtest * clean up * dont initialize game info because we are missing stuff
217 lines
6.8 KiB
Common Lisp
217 lines
6.8 KiB
Common Lisp
;;-*-Lisp-*-
|
|
(in-package goal)
|
|
|
|
;; name: collide-func.gc
|
|
;; name in dgo: collide-func
|
|
;; dgos: GAME, ENGINE
|
|
|
|
;; This file contains the primitive intersection functions used for collision.
|
|
;; Most take a description of primitive and a "probe"
|
|
;; The probe has an origin and a direction. The length of the direction vector is the length
|
|
;; of the probe.
|
|
|
|
;; Generally, collision functions will return the fraction of the probe to reach the primitive.
|
|
;; For example, if the probe is 5.0 long, and hits the primitive 2.0 away from the probe origin,
|
|
;; the return value (u) would be 0.4.
|
|
|
|
;; If (u) would be > 1.0, then it counts as "not intersecting" (object too far away)
|
|
;; If (u) would be < 0.0, then it counts as "not intersecting" (object behind probe)
|
|
;; If there's a miss, return COLLISION_MISS, a large negative number.
|
|
;; If we are inside of the primitive, return 0.0
|
|
|
|
(defconstant COLLISION_MISS -100000000.0)
|
|
|
|
|
|
|
|
(defun raw-ray-sphere-intersect ((arg0 float))
|
|
"DANGER: this function takes two arguments by vf registers.
|
|
As a result, it doesn't work properly in OpenGOAL. See the functions below."
|
|
(local-vars
|
|
(v1-1 float)
|
|
(v1-2 float)
|
|
(v1-4 number)
|
|
(a0-1 float)
|
|
(a0-2 float)
|
|
(a0-3 int)
|
|
(a1-0 float)
|
|
)
|
|
(crash!)
|
|
(rlet ((Q :class vf)
|
|
(vf0 :class vf)
|
|
(vf1 :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)
|
|
(.mov vf3 arg0) ;; vf3 = radius
|
|
;; sphere is at the origin, vf1 is source of the ray (o)
|
|
;; vf2 is the ray's unit vector (u)
|
|
(.mul.vf vf4 vf2 vf2) ;; vf4 = u.^2
|
|
(.mul.vf vf3 vf3 vf3) ;; vf3 = r^2
|
|
(.mul.vf vf6 vf1 vf1) ;; vf6 = o.^2
|
|
(.mul.vf vf5 vf2 vf1) ;; vf5 = u . o
|
|
(.add.y.vf vf4 vf4 vf4 :mask #b1)
|
|
(let ((result (the-as float 0)))
|
|
(.add.x.vf vf6 vf6 vf6 :mask #b10)
|
|
(.sub.x.vf vf6 vf6 vf3 :mask #b100)
|
|
(.add.z.vf vf4 vf4 vf4 :mask #b1)
|
|
(.add.x.vf vf5 vf5 vf5 :mask #b10)
|
|
(let ((v1-0 (the-as float 0)))
|
|
(.add.z.vf vf6 vf6 vf6 :mask #b10)
|
|
(.div.vf Q vf0 vf4 :fsf #b11 :ftf #b0)
|
|
(.add.z.vf vf5 vf5 vf5 :mask #b10)
|
|
(.mov a0-1 vf4)
|
|
(.mul.x.vf vf7 vf6 vf4)
|
|
(.mov a1-0 vf6)
|
|
(.mul.vf vf8 vf5 vf5)
|
|
(b! (< (the-as int a1-0) 0) cfg-7 :delay (set! a0-2 a0-1))
|
|
(.mul.vf vf4 vf0 Q :mask #b1000)
|
|
(.sub.vf vf9 vf8 vf7)
|
|
(b! (= a0-2 v1-0) cfg-6 :delay (.mov v1-1 vf5))
|
|
)
|
|
(.sqrt.vf Q vf9 :ftf #b1)
|
|
(b! (>= (the-as int v1-1) 0) cfg-6 :delay (.mov v1-2 vf9))
|
|
(b! (< (the-as int v1-2) 0) cfg-6 :delay 1.0)
|
|
(.add.x.vf vf6 vf5 vf4)
|
|
(.mov v1-4 vf6)
|
|
(.mul.vf vf6 vf6 vf6)
|
|
(.mul.vf vf9 vf0 Q :mask #b1000)
|
|
(.sub.vf vf6 vf9 vf6)
|
|
(.add.w.vf vf9 vf5 vf9 :mask #b10)
|
|
(.mov a0-3 vf6)
|
|
(.mul.w.vf vf9 vf9 vf4 :mask #b10)
|
|
(b!
|
|
(< (logand (the-as uint v1-4) (the-as uint a0-3)) 0)
|
|
cfg-6
|
|
:delay
|
|
(.sub.y.vf vf4 vf0 vf9)
|
|
)
|
|
(b! #t cfg-7 :delay (.mov result vf4))
|
|
(label cfg-6)
|
|
(set! result -100000000.0)
|
|
(label cfg-7)
|
|
(the-as float result)
|
|
)
|
|
)
|
|
)
|
|
|
|
(defmacro pc-port-do-raw-ray-sphere-intersect (rad vf1-val vf2-val)
|
|
"Calls to raw-ray-sphere-intersect should be replaced with this macro,
|
|
and this should be given vf1, vf2, which contain the origin and direction of the probe."
|
|
`(let ((vf1-storage (new 'stack-no-clear 'vector))
|
|
(vf2-storage (new 'stack-no-clear 'vector))
|
|
)
|
|
(.svf (&-> vf1-storage quad) ,vf1-val)
|
|
(.svf (&-> vf2-storage quad) ,vf2-val)
|
|
(pc-port-raw-ray-sphere-implementation ,rad vf1-storage vf2-storage)
|
|
)
|
|
)
|
|
|
|
|
|
(defun pc-port-raw-ray-sphere-implementation ((rad float) (vf1-val vector) (vf2-val vector))
|
|
"This is one of the main primitives for collision.
|
|
Assumes a sphere of radius rad is at the origin.
|
|
Handles:
|
|
- miss (return MISS)
|
|
- behind (return MISS)
|
|
- too far away (return MISS)
|
|
- inside (return 0)
|
|
"
|
|
(local-vars
|
|
(v1-1 int)
|
|
(v1-2 int)
|
|
(v1-4 int)
|
|
(a0-1 float)
|
|
(a0-2 float)
|
|
(a0-3 int)
|
|
(a1-0 int)
|
|
)
|
|
(rlet ((Q :class vf)
|
|
(vf0 :class vf)
|
|
(vf1 :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)
|
|
(.lvf vf1 (&-> vf1-val quad))
|
|
(.lvf vf2 (&-> vf2-val quad))
|
|
(.mov vf3 rad)
|
|
(.mul.vf vf4 vf2 vf2)
|
|
(.mul.vf vf3 vf3 vf3)
|
|
(.mul.vf vf6 vf1 vf1)
|
|
(.mul.vf vf5 vf2 vf1)
|
|
(.add.y.vf vf4 vf4 vf4 :mask #b1)
|
|
(let ((result (the-as float 0)))
|
|
(.add.x.vf vf6 vf6 vf6 :mask #b10)
|
|
(.sub.x.vf vf6 vf6 vf3 :mask #b100)
|
|
(.add.z.vf vf4 vf4 vf4 :mask #b1)
|
|
(.add.x.vf vf5 vf5 vf5 :mask #b10)
|
|
(let ((v1-0 (the-as float 0)))
|
|
(.add.z.vf vf6 vf6 vf6 :mask #b10)
|
|
(.div.vf Q vf0 vf4 :fsf #b11 :ftf #b0)
|
|
(.add.z.vf vf5 vf5 vf5 :mask #b10)
|
|
(.mov a0-1 vf4)
|
|
(.mul.x.vf vf7 vf6 vf4)
|
|
(.mov a1-0 vf6)
|
|
(.mul.vf vf8 vf5 vf5)
|
|
(b! (< (the-as int a1-0) 0) cfg-7 :delay (set! a0-2 a0-1)) ;; in the sphere
|
|
(.mul.vf vf4 vf0 Q :mask #b1000)
|
|
(.sub.vf vf9 vf8 vf7)
|
|
(b! (= a0-2 v1-0) cfg-6 :delay (.mov v1-1 vf5)) ;; bad denominator in division
|
|
)
|
|
(.sqrt.vf Q vf9 :ftf #b1)
|
|
(b! (>= (the-as int v1-1) 0) cfg-6 :delay (.mov v1-2 vf9)) ;; wrong dir
|
|
(b! (< (the-as int v1-2) 0) cfg-6 :delay 1.0) ;; bad sqrt
|
|
(.add.x.vf vf6 vf5 vf4)
|
|
(.mov v1-4 vf6)
|
|
(.mul.vf vf6 vf6 vf6)
|
|
(.mul.vf vf9 vf0 Q :mask #b1000)
|
|
(.sub.vf vf6 vf9 vf6)
|
|
(.add.w.vf vf9 vf5 vf9 :mask #b10)
|
|
(.mov a0-3 vf6)
|
|
(.mul.w.vf vf9 vf9 vf4 :mask #b10)
|
|
|
|
;; too far.
|
|
(b! (< (logand (the-as int v1-4) (the-as int a0-3)) 0)
|
|
cfg-6
|
|
:delay (.sub.y.vf vf4 vf0 vf9)
|
|
)
|
|
(b! #t cfg-7 :delay (.mov result vf4))
|
|
(label cfg-6)
|
|
(set! result -100000000.0)
|
|
(label cfg-7)
|
|
(the-as float result)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
(defun ray-sphere-intersect ((ray-origin vector) (ray-dir vector) (sph-origin vector) (radius float))
|
|
"Intersect a ray and sphere. Will return 0 if you are in the sphere, -huge number if you don't hit it.
|
|
Returns the length of the ray to the first intersection."
|
|
|
|
;; offset stuff as if the sphere is at the origin.
|
|
(rlet ((vf1 :class vf)
|
|
(vf2 :class vf)
|
|
)
|
|
(.lvf vf1 (&-> ray-origin quad))
|
|
(.lvf vf2 (&-> sph-origin quad))
|
|
(.sub.vf vf1 vf1 vf2) ;; the sphere is at the origin in the actual intersection.
|
|
(.lvf vf2 (&-> ray-dir quad))
|
|
;;(raw-ray-sphere-intersect radius)
|
|
(pc-port-do-raw-ray-sphere-intersect radius vf1 vf2)
|
|
)
|
|
)
|