jak-project/goal_src/jak3/engine/nav/nav-mesh-h.gc
Hat Kid 2969833b2d
decomp3: more engine stuff, detect non-virtual state inheritance (#3377)
- `speech`
- `ambient`
- `water-h`
- `vol-h`
- `generic-obs`
- `carry-h`
- `pilot-h`
- `board-h`
- `gun-h`
- `flut-h`
- `indax-h`
- `lightjak-h`
- `darkjak-h`
- `target-util`
- `history`
- `collide-reaction-target`
- `logic-target`
- `sidekick`
- `projectile`
- `voicebox`
- `ragdoll-edit`
- most of `ragdoll` (not added to gsrc yet)
- `curves`
- `find-nearest`
- `lightjak-wings`
- `target-handler`
- `target-anim`
- `target`
- `target2`
- `target-swim`
- `target-lightjak`
- `target-invisible`
- `target-death`
- `target-gun`
- `gun-util`
- `board-util`
- `target-board`
- `board-states`
- `mech-h`
- `vol`
- `vent`
- `viewer`
- `gem-pool`
- `collectables`
- `crates`
- `secrets-menu`

Additionally:

- Detection of non-virtual state inheritance
- Added a config file that allows overriding the process stack size set
by `stack-size-set!` calls
- Fix for integer multiplication with `r0`
- Fixed detection for the following macros:
	- `static-attack-info`
- `defpart` and `defpartgroup` (probably still needs adjustments, uses
Jak 2 implementation at the moment)
- `sound-play` (Jak 3 seems to always call `sound-play-by-name` with a
`sound-group` of 0, so the macro has been temporarily defaulted to use
that)

One somewhat significant change made here that should be noted is that
the return type of `process::init-from-entity!` was changed to `object`.
I've been thinking about this for a while, since it looks a bit nicer
without the `(none)` at the end and I have recently encountered init
methods that early return `0`.
2024-03-03 15:15:27 -05:00

552 lines
16 KiB
Common Lisp

;;-*-Lisp-*-
(in-package goal)
;; name: nav-mesh-h.gc
;; name in dgo: nav-mesh-h
;; dgos: GAME
(declare-type grid-hash structure)
(declare-type sphere-hash structure)
(defenum nav-mesh-flag
:type uint8
:bitfield #t
(water 0)
(dummy 1)
)
(define-extern nav-mesh-connect-from-ent (function process-drawable symbol))
;; DECOMP BEGINS
(deftype nav-mesh-work-debug (structure)
"Debug outputs for the nav-mesh assembly functions"
((debug-vec1 vector :inline)
(debug-vec2 vector :inline)
(debug-vec3 vector :inline)
(debug-vec4 vector :inline)
(debug-vec5 vector :inline)
(debug-vec6 vector :inline)
(debug-vec7 vector :inline)
(debug-vec8 vector :inline)
(debug-vec9 vector :inline)
(debug-vec10 vector :inline)
(debug-vec11 vector :inline)
(debug-vec12 vector :inline)
(sphere-array sphere 16 :inline)
)
)
(deftype nav-mesh-work (structure)
"Workspace for nav-mesh processing functions."
((vert0-table int8 4)
(vert1-table int8 4)
(edge-mask-table uint8 3)
(pad0 uint32)
(deg-to-rad float)
(rad-to-deg float)
(nav-poly-min-dist float)
(nav-poly-epsilon float)
(sphere-array sphere 16 :inline)
(debug nav-mesh-work-debug)
(work-struct-in-scratch int8)
(mesh-struct-in-scratch int8)
(polys-in-scratch int8)
(mesh nav-mesh)
(nav basic)
(poly0 nav-poly)
(poly1 nav-poly)
(poly-id int32)
)
)
(deftype nav-mesh-link (structure)
"Link between two different meshes"
((id uint32)
(dest-mesh-id uint32)
(src-link-poly-id uint8)
(src-switch-poly-id uint8)
(dest-link-poly-id uint8)
(dest-switch-poly-id uint8)
(dest-mesh nav-mesh)
)
)
(deftype nav-poly (structure)
"Polygon within a nav-mesh. Can be a tri or quad.
Based on the implementation of point-poly-intersection?, these should likely be convex."
((data uint8 64 :offset 0)
(vertex vector 4 :inline :overlay-at (-> data 0))
(vertex0 vector :inline :overlay-at (-> vertex 0))
(vertex1 vector :inline :overlay-at (-> vertex 1))
(vertex2 vector :inline :overlay-at (-> vertex 2))
(vertex3 vector :inline :overlay-at (-> vertex 3))
(id uint8 :overlay-at (-> data 12))
(pat uint8 :overlay-at (-> data 13))
(vertex-count uint8 :overlay-at (-> data 14))
(link uint8 :overlay-at (-> data 15))
(adj-poly uint8 4 :overlay-at (-> data 28))
(adj-poly0 uint8 :overlay-at (-> adj-poly 0))
(adj-poly1 uint8 :overlay-at (-> adj-poly 1))
(adj-poly2 uint8 :overlay-at (-> adj-poly 2))
(adj-poly3 uint8 :overlay-at (-> adj-poly 3))
(min-y float :overlay-at (-> data 44))
(max-y float :overlay-at (-> data 60))
)
)
(deftype nav-vertex (vector)
()
)
(deftype nav-sphere (structure)
((trans sphere :inline)
)
)
(deftype nav-ray (structure)
((current-pos vector :inline)
(dir vector :inline)
(dest-pos vector :inline)
(current-poly nav-poly)
(next-poly nav-poly)
(len meters)
(last-edge int8)
(ignore uint8)
(terminated symbol)
(reached-dest symbol)
(hit-boundary symbol)
(hit-gap symbol)
)
)
(deftype nav-route-portal (structure)
((vertex nav-vertex 2 :inline)
(next-poly nav-poly)
(edge-index int8)
)
)
(deftype nav-find-poly-parms (structure)
((point vector :inline)
(y-threshold float)
(ignore uint8)
(poly nav-poly)
(dist float)
(point-inside? symbol)
)
)
(deftype clamp-travel-vector-to-mesh-return-info (structure)
((found-boundary symbol)
(intersection vector :inline)
(boundary-normal vector :inline)
(prev-normal vector :inline)
(next-normal vector :inline)
(poly nav-poly)
(gap-poly nav-poly)
(edge int8)
(ignore uint8)
(vert-prev vector :inline)
(vert-0 vector :inline)
(vert-1 vector :inline)
(vert-next vector :inline)
)
)
(deftype nav-mesh (basic)
"Mesh used for creature/enemy navigation."
((work nav-mesh-work)
(poly-array (inline-array nav-poly))
(static-sphere-count uint8)
(poly-count uint8)
(nav-control-count uint8)
(max-nav-control-count uint8)
(route (pointer uint8))
(poly-hash grid-hash)
(nav-control-array (inline-array nav-control))
(sphere-hash sphere-hash)
(static-sphere (inline-array sphere))
(user-list engine)
(next-nav-mesh surface)
(prev-nav-mesh surface)
(bounds sphere :inline)
(origin vector :inline :overlay-at (-> bounds data 0))
(entity entity)
(link-array (inline-array nav-mesh-link))
(link-count uint8)
(flags nav-mesh-flag)
(pad1 uint8 2)
(nearest-y-threshold meters)
(water-max-height meters)
(pad2 uint32 7)
)
(:methods
(nav-mesh-method-9 () none)
(nav-mesh-method-10 () none)
(nav-mesh-method-11 () none)
(nav-mesh-method-12 () none)
(nav-mesh-method-13 () none)
(nav-mesh-method-14 () none)
(nav-mesh-method-15 () none)
(nav-mesh-method-16 () none)
(nav-mesh-method-17 () none)
(advance-ray-to-nearest-poly-edge-or-dest! (_type_ nav-ray) none)
(nav-mesh-method-19 () none)
(nav-mesh-method-20 () none)
(nav-mesh-method-21 () none)
(nav-mesh-method-22 () none)
(nav-mesh-method-23 () none)
(nav-mesh-method-24 () none)
(nav-mesh-method-25 () none)
(nav-mesh-method-26 () none)
(nav-mesh-method-27 () none)
(nav-mesh-method-28 () none)
(nav-mesh-method-29 () none)
(nav-mesh-method-30 () none)
(nav-mesh-method-31 () none)
(nav-mesh-method-32 () none)
(nav-mesh-method-33 () none)
(nav-mesh-method-34 () none)
(nav-mesh-method-35 () none)
(nav-mesh-method-36 () none)
(nav-mesh-method-37 () none)
(nav-mesh-method-38 () none)
(nav-mesh-method-39 () none)
(point-in-poly? (_type_ nav-poly vector) symbol)
(nav-mesh-method-41 () none)
(closest-point-on-boundary (_type_ nav-poly vector vector) vector)
(nav-mesh-method-43 () none)
(project-point-into-poly-2d (_type_ nav-poly vector vector) vector)
(nav-mesh-method-45 () none)
(nav-mesh-method-46 () none)
(nav-mesh-method-47 () none)
(nav-mesh-method-48 () none)
(nav-mesh-method-49 () none)
)
)
(defun vector-normalize-unity! ((arg0 vector))
"Normalize a vector (xyz only) in place."
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(let ((v0-0 arg0))
(let ((f0-0 1.0))
(.lvf vf1 (&-> v0-0 quad))
(.mul.vf vf2 vf1 vf1 :mask #b111)
(let ((v1-1 f0-0))
(.mov vf3 v1-1)
)
)
(.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 (&-> v0-0 quad) vf1)
v0-0
)
)
)
(defun vector-normalize-unity-copy! ((arg0 vector) (arg1 vector))
"Normalize a vector (xyz only)"
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(set! (-> arg0 quad) (-> arg1 quad))
(let ((v0-0 arg0))
(let ((f0-0 1.0))
(.lvf vf1 (&-> v0-0 quad))
(.mul.vf vf2 vf1 vf1 :mask #b111)
(let ((v1-2 f0-0))
(.mov vf3 v1-2)
)
)
(.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 (&-> v0-0 quad) vf1)
v0-0
)
)
)
(defun-debug debug-validate-current-poly ()
"Not implemented."
#f
)
(defun init-ray ((arg0 nav-ray))
"Set up a nav-ray. Assumes that dest-pos and current-pos are set."
(rlet ((acc :class vf)
(Q :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(vector-! (-> arg0 dir) (-> arg0 dest-pos) (-> arg0 current-pos))
(set! (-> arg0 dir y) 0.0)
(let ((v1-1 (-> arg0 dir)))
(let ((f0-1 1.0))
(.lvf vf1 (&-> v1-1 quad))
(.mul.vf vf2 vf1 vf1 :mask #b111)
(let ((a1-2 f0-1))
(.mov vf3 a1-2)
)
)
(.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 (&-> v1-1 quad) vf1)
)
(set! (-> arg0 next-poly) #f)
(set! (-> arg0 len) 0.0)
(set! (-> arg0 last-edge) -1)
(set! (-> arg0 terminated) #f)
(set! (-> arg0 reached-dest) #f)
(set! (-> arg0 hit-boundary) #f)
(set! (-> arg0 hit-gap) #f)
(set! (-> arg0 ignore) (the-as uint 3))
0
(none)
)
)
(defun point-poly-intersection? ((mesh nav-mesh) (pt vector) (num-verts int) (verts (inline-array vector)))
"Check if a point is inside a poly."
(let ((v1-1 (-> mesh work vert0-table))
(a0-2 (-> mesh work vert1-table))
)
(dotimes (t0-0 num-verts)
(let* ((t1-3 (-> verts (-> v1-1 t0-0)))
(t2-3 (-> verts (-> a0-2 t0-0)))
(f0-1 (- (-> t1-3 z) (-> t2-3 z)))
(f1-2 (- (-> t2-3 x) (-> t1-3 x)))
(f2-2 (- (-> pt x) (-> t1-3 x)))
(f3-2 (- (-> pt z) (-> t1-3 z)))
(f0-3 (+ (* f2-2 f0-1) (* f3-2 f1-2)))
)
(if (< 0.0 f0-3)
(return #f)
)
)
)
)
#t
)
(defmethod point-in-poly? ((this nav-mesh) (arg0 nav-poly) (arg1 vector))
"Check if a point is inside a poly of this mesh"
(let* ((a3-0 this)
(v1-0 arg1)
(a0-1 (-> arg0 vertex-count))
(a1-1 (-> arg0 vertex))
(a2-2 (-> a3-0 work vert0-table))
(a3-2 (-> a3-0 work vert1-table))
)
(dotimes (t0-0 (the-as int a0-1))
(let* ((t1-3 (-> a1-1 (-> a2-2 t0-0)))
(t2-3 (-> a1-1 (-> a3-2 t0-0)))
(f0-1 (- (-> t1-3 z) (-> t2-3 z)))
(f1-2 (- (-> t2-3 x) (-> t1-3 x)))
(f2-2 (- (-> v1-0 x) (-> t1-3 x)))
(f3-2 (- (-> v1-0 z) (-> t1-3 z)))
(f0-3 (+ (* f2-2 f0-1) (* f3-2 f1-2)))
)
(if (< 0.0 f0-3)
(return #f)
)
)
)
)
#t
)
(defmethod closest-point-on-boundary ((this nav-mesh) (arg0 nav-poly) (arg1 vector) (arg2 vector))
"Find the point on the polygon edge that is closest to the query point."
(local-vars (sv-48 vector) (sv-52 vector) (sv-56 number))
(set! sv-48 (new 'stack-no-clear 'vector))
(set! sv-52 (new 'stack-no-clear 'vector))
(set! sv-56 10000000000000000000000000000000000000.0)
(let* ((s3-0 (-> arg0 vertex-count))
(v1-3 (the-as int (+ s3-0 -1)))
)
(dotimes (s2-0 (the-as int s3-0))
(let ((f0-1 (vector-segment-distance-point! arg2 (-> arg0 vertex v1-3) (-> arg0 vertex s2-0) sv-48)))
(when (< f0-1 (the-as float sv-56))
(set! sv-56 f0-1)
(set! (-> sv-52 quad) (-> sv-48 quad))
)
)
(set! v1-3 s2-0)
)
)
(set! (-> arg1 quad) (-> sv-52 quad))
arg1
)
(defmethod project-point-into-poly-2d ((this nav-mesh) (arg0 nav-poly) (arg1 vector) (arg2 vector))
"Find the point in the polygon closest to the query point."
(local-vars (sv-48 vector) (sv-52 vector) (sv-56 number))
(cond
((point-in-poly? this arg0 arg2)
(set! (-> arg1 quad) (-> arg2 quad))
)
(else
(let ((s5-1 arg1))
(set! sv-48 (new 'stack-no-clear 'vector))
(set! sv-52 (new 'stack-no-clear 'vector))
(set! sv-56 10000000000000000000000000000000000000.0)
(let* ((s2-0 (-> arg0 vertex-count))
(v1-6 (the-as int (+ s2-0 -1)))
)
(dotimes (s1-0 (the-as int s2-0))
(let ((f0-1 (vector-segment-distance-point! arg2 (-> arg0 vertex v1-6) (-> arg0 vertex s1-0) sv-48)))
(when (< f0-1 (the-as float sv-56))
(set! sv-56 f0-1)
(set! (-> sv-52 quad) (-> sv-48 quad))
)
)
(set! v1-6 s1-0)
)
)
(set! (-> s5-1 quad) (-> sv-52 quad))
)
)
)
arg1
)
(defmethod advance-ray-to-nearest-poly-edge-or-dest! ((this nav-mesh) (arg0 nav-ray))
(local-vars
(sv-16 int)
(sv-24 nav-mesh-work)
(sv-28 nav-poly)
(sv-32 uint)
(sv-36 (pointer int8))
(sv-40 (pointer int8))
(sv-44 float)
(sv-48 float)
(sv-52 vector)
(sv-56 vector)
(sv-60 float)
(sv-64 float)
(sv-68 uint)
)
(set! sv-16 -1)
(set! sv-24 (-> this work))
(set! sv-28 (-> arg0 current-poly))
(set! sv-32 (-> arg0 current-poly vertex-count))
(set! sv-36 (-> this work vert0-table))
(set! sv-40 (-> this work vert1-table))
(set! sv-44 (- (-> arg0 dest-pos x) (-> arg0 current-pos x)))
(set! sv-48 (- (-> arg0 dest-pos z) (-> arg0 current-pos z)))
(dotimes (v1-9 (the-as int sv-32))
(set! sv-52 (-> sv-28 vertex (-> sv-36 v1-9)))
(set! sv-56 (-> sv-28 vertex (-> sv-40 v1-9)))
(set! sv-60 (- (-> sv-52 z) (-> sv-56 z)))
(set! sv-64 (- (-> sv-56 x) (-> sv-52 x)))
(let ((f0-10 (+ (* sv-44 sv-60) (* sv-48 sv-64))))
(when (< 0.0 f0-10)
(let ((f1-10
(+ (* sv-60 (- (-> sv-52 x) (-> arg0 current-pos x))) (* sv-64 (- (-> sv-52 z) (-> arg0 current-pos z))))
)
)
(when (< f1-10 f0-10)
(set! sv-16 v1-9)
(let ((f0-12 (fmax 0.0 (/ f1-10 f0-10))))
(set! sv-44 (* sv-44 f0-12))
(set! sv-48 (* sv-48 f0-12))
)
)
)
)
)
)
(let ((f0-16 (+ (* sv-44 (-> arg0 dir x)) (* sv-48 (-> arg0 dir z)))))
(+! (-> arg0 len) f0-16)
)
0
(set! (-> arg0 next-poly) #f)
(cond
((= sv-16 -1)
(set! (-> arg0 current-pos quad) (-> arg0 dest-pos quad))
(set! (-> arg0 reached-dest) #t)
(set! (-> arg0 terminated) #t)
)
(else
(+! (-> arg0 current-pos x) sv-44)
(+! (-> arg0 current-pos z) sv-48)
(set! sv-68 (-> sv-28 adj-poly sv-16))
(if (!= sv-68 255)
(set! (-> arg0 next-poly) (-> this poly-array sv-68))
)
(cond
((and (-> arg0 next-poly) (not (logtest? (-> arg0 next-poly pat) (-> arg0 ignore))))
(set! (-> arg0 current-poly) (-> arg0 next-poly))
)
(else
(set! (-> arg0 last-edge) sv-16)
(if (-> arg0 next-poly)
(set! (-> arg0 hit-gap) #t)
(set! (-> arg0 hit-boundary) #t)
)
(set! (-> arg0 terminated) #t)
)
)
)
)
0
(none)
)
(defun-debug nav-sphere-from-cam ()
"Print out a SPHEREM from the current camera position, possibly used by their level-building tool."
(let ((v1-0 (camera-pos)))
(format #t "SPHEREM(~4,,1M, ~4,,1M, ~4,,1M, 1.0)~%" (-> v1-0 x) (-> v1-0 y) (-> v1-0 z))
)
0
(none)
)