;;-*-Lisp-*-
(in-package goal)

;; name: nav-mesh.gc
;; name in dgo: nav-mesh
;; dgos: ENGINE, GAME

;; DECOMP BEGINS

(rlet ((vf0 :class vf) (vf4 :class vf) (vf5 :class vf) (vf6 :class vf))
(init-vf0-vector)

(define *debug-nav-control-output* #f)

(define *debug-nav-control* #f)

(define *debug-nav-mesh-output* #f)

(define *debug-nav-ray* (the-as nav-ray #f))

(define *debug-ray-offset* (new 'static 'vector))

(define *debug-offset* (new 'static 'vector :y 4096.0 :w 1.0))

(define *nav-mesh-work* (new 'static 'nav-mesh-work
                          :vert0-table (new 'static 'array int8 4 0 1 2 3)
                          :vert1-table (new 'static 'array int8 4 1 2 3 0)
                          :edge-mask-table (new 'static 'array uint8 3 #x1 #x2 #x4)
                          :deg-to-rad 0.000095873795
                          :rad-to-deg 10430.379
                          :nav-poly-min-dist 204.8
                          :nav-poly-epsilon 40.96
                          :debug (new 'static 'nav-mesh-work-debug)
                          :work-struct-in-scratch 1
                          :mesh-struct-in-scratch 1
                          :polys-in-scratch 1
                          )
        )

(define *default-nav-mesh* (new 'static 'nav-mesh
                             :poly-array (new 'static 'inline-array nav-poly 1
                               (new 'static 'nav-poly
                                 :vertex (new 'static 'inline-array vector 4
                                   (new 'static 'vector :w -175458100000000000000000000000000000000.0)
                                   (new 'static 'vector :w (the-as float #xffffffff))
                                   (new 'static 'vector)
                                   (new 'static 'vector)
                                   )
                                 )
                               )
                             :poly-count #x1
                             :max-nav-control-count #x80
                             :nav-control-array (new 'static 'inline-array nav-control 128
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               (new 'static 'nav-control)
                               )
                             )
        )

(kmemopen global "nav-mesh")

(let ((gp-0 *default-nav-mesh*))
  (set! (-> gp-0 work) *nav-mesh-work*)
  (if (zero? (-> gp-0 user-list))
      (set! (-> gp-0 user-list) (new 'global 'engine 'nav-engine 128 connection))
      )
  (when (zero? (-> gp-0 poly-hash))
    (set! (-> gp-0 poly-hash) (new 'global 'grid-hash 16))
    (let ((v1-12 (new 'static 'inline-array vector 2 (new 'static 'vector) (new 'static 'vector))))
      (vector-reset! (-> v1-12 0))
      (vector-reset! (-> v1-12 1))
      (let ((a1-3 (-> v1-12 0)))
        (let ((a0-5 (-> v1-12 0)))
          (let ((a2-3 -4096.0))
            (.mov vf6 a2-3)
            )
          (.lvf vf4 (&-> a0-5 quad))
          )
        (.add.x.vf.w vf5 vf0 vf0)
        (.add.x.vf.xyz vf5 vf4 vf6)
        (.svf (&-> a1-3 quad) vf5)
        )
      (let ((a1-4 (-> v1-12 1)))
        (let ((a0-6 (-> v1-12 1)))
          (let ((a2-5 4096.0))
            (.mov vf6 a2-5)
            )
          (.lvf vf4 (&-> a0-6 quad))
          )
        (.add.x.vf.w vf5 vf0 vf0)
        (.add.x.vf.xyz vf5 vf4 vf6)
        (.svf (&-> a1-4 quad) vf5)
        )
      (update-grid-for-objects-in-box
        (-> gp-0 poly-hash)
        (the-as int (-> gp-0 poly-count))
        (-> v1-12 0)
        (-> v1-12 1)
        )
      )
    )
  )

(kmemclose)

(defun nav-mesh-connect-from-ent ((arg0 process-drawable))
  "Connect this process to the nav-mesh associate with the entity that spawned the process"
  (let ((s5-0 (nav-mesh-from-res-tag (-> arg0 entity) 'nav-mesh-actor 0)))
    (cond
      (s5-0
        (if (zero? (-> s5-0 user-list))
            (format 0 "nav-mesh-connect-from-ent: nav mesh not initialized!~%")
            )
        (if (add-connection (-> s5-0 user-list) arg0 nothing arg0 #f (-> arg0 root))
            #t
            )
        )
      (else
        (if (-> arg0 entity)
            (logior! (-> arg0 entity extra perm status) (entity-perm-status error))
            )
        #f
        )
      )
    )
  )

(defun-debug connection-validate ((arg0 connection))
  (when (zero? arg0)
    (break!)
    0
    )
  (when (zero? (-> arg0 next1))
    (break!)
    0
    )
  (when (zero? (-> arg0 prev1))
    (break!)
    0
    )
  (when (-> arg0 next1)
    (when (!= arg0 (-> arg0 next1 prev1))
      (break!)
      0
      )
    )
  (when (-> arg0 prev1)
    (when (!= arg0 (-> arg0 prev1 next1))
      (break!)
      0
      )
    )
  0
  (none)
  )

(defun-debug connection-list-validate ((arg0 (inline-array connection)))
  (let ((gp-0 (the-as object (&-> arg0 3 prev1))))
    (while gp-0
      (connection-validate (the-as connection gp-0))
      (set! gp-0 (-> (the-as connection gp-0) next1))
      )
    )
  #f
  )

(defun-debug nav-control-validate ((arg0 process-drawable))
  (let ((s5-0 (the-as object (-> arg0 nav))))
    (when (and (-> arg0 nav) (!= arg0 (-> arg0 nav process)))
      (format 0 "process pointing to wrong nav-control!~%")
      (break!)
      0
      )
    (let ((s4-0 (-> arg0 nav state mesh)))
      (when (or (not s4-0) (zero? s4-0))
        (format 0 "nav control has invalid mesh~%")
        (break!)
        0
        )
      (let ((v1-12 (- (the-as int s5-0) (the-as uint (the-as int (-> s4-0 nav-control-array 0))))))
        (when (or (< (the-as uint v1-12) 0)
                  (< (the-as uint (* (the-as uint 288) (-> s4-0 nav-control-count))) (the-as uint v1-12))
                  )
          (format 0 "nav control (~,,8x) is not in the mesh's nav-control-array!~%" (the-as nav-control s5-0))
          (inspect s4-0)
          (break!)
          0
          )
        )
      )
    )
  (connection-list-validate (the-as (inline-array connection) arg0))
  0
  (none)
  )

(defun-debug debug-validate-nav-poly ((arg0 nav-mesh-link) (arg1 nav-poly))
  (set! (-> *nav-mesh-work* poly1) (-> *nav-mesh-work* poly0))
  (set! (-> *nav-mesh-work* poly0) arg1)
  (when arg1
    (let ((a2-1 arg1)
          (a3-0 (+ (-> arg0 dest-mesh-id) 0))
          (t0-0 (+ (-> arg0 dest-mesh-id) (* (+ (-> arg0 src-switch-poly-id) -1) 64)))
          )
      (when (or (< (the-as uint a2-1) a3-0) (< t0-0 (the-as uint a2-1)))
        (format 0 "validate-nav-poly: bad poly pointer ~x range ~x ~x~%" a2-1 a3-0 t0-0)
        (break!)
        0
        )
      )
    )
  0
  (none)
  )

(defmethod initialize-nav-mesh! ((this entity-nav-mesh))
  "Initialize the nav-mesh in this entity."
  (let ((v1-0 (-> this nav-mesh)))
    (if (nonzero? v1-0)
        (init-from-entity v1-0 this)
        )
    )
  0
  (none)
  )

(defmethod birth! ((this entity-nav-mesh))
  (let ((a0-1 (-> this nav-mesh)))
    (if (nonzero? a0-1)
        (handle-birth a0-1)
        )
    )
  this
  )

(defmethod kill! ((this entity-nav-mesh))
  (if (-> this nav-mesh)
      (handle-kill (-> this nav-mesh))
      )
  this
  )

(defmethod debug-draw ((this entity-nav-mesh))
  (add-debug-x
    #t
    (bucket-id debug-no-zbuf1)
    (-> this nav-mesh bounds)
    (new 'static 'rgba :r #x80 :g #xff :b #x80 :a #x80)
    )
  (let ((s5-0 (new 'stack-no-clear 'vector)))
    (set! (-> s5-0 quad) (-> this nav-mesh bounds quad))
    (let ((a0-6 (new 'stack 'random-generator)))
      (set! (-> a0-6 seed) (-> this aid))
      (let* ((v1-4 (rand-uint31-gen a0-6))
             (f30-0 (* 182.04445 (the float (logand v1-4 #xffff))))
             )
        (+! (-> s5-0 x) (* 4096.0 (cos f30-0)))
        (+! (-> s5-0 z) (* 4096.0 (sin f30-0)))
        )
      )
    (add-debug-text-3d
      #t
      (bucket-id debug-no-zbuf1)
      (res-lump-struct this 'name string)
      s5-0
      (font-color white)
      (new 'static 'vector2h :data (new 'static 'array int16 2 0 8))
      )
    (let ((s4-1 add-debug-text-3d)
          (s3-1 #t)
          (s2-1 (bucket-id debug-no-zbuf1))
          )
      (format (clear *temp-string*) "aid ~D" (-> this aid))
      (s4-1
        s3-1
        (the-as bucket-id s2-1)
        *temp-string*
        s5-0
        (font-color white)
        (new 'static 'vector2h :data (new 'static 'array int16 2 0 16))
        )
      )
    )
  (debug-draw (-> this nav-mesh))
  0
  (none)
  )

(defmethod get-simple-travel-vector ((this entity-actor) (arg0 vector) (arg1 vector) (arg2 vector) (arg3 object) (arg4 float))
  (local-vars (at-0 int) (at-1 int))
  (with-pp
    (rlet ((vf0 :class vf)
           (vf1 :class vf)
           (vf2 :class vf)
           )
      (init-vf0-vector)
      (let ((gp-0 (nav-mesh-from-res-tag this 'nav-mesh-actor 0)))
        (cond
          (gp-0
            (let ((v1-0 arg0))
              (.lvf vf1 (&-> arg2 quad))
              (let ((f0-0 (seconds-per-frame)))
                (.mov at-0 f0-0)
                )
              (.mov vf2 at-0)
              (.mov.vf.w vf1 vf0)
              (.mul.x.vf.xyz vf1 vf1 vf2)
              (.svf (&-> v1-0 quad) vf1)
              )
            (let ((s3-1 (new 'stack-no-clear 'nav-find-poly-parms)))
              (vector-! (-> s3-1 point) arg1 (-> gp-0 bounds))
              (set! (-> s3-1 y-threshold) 40960.0)
              (set! (-> s3-1 ignore) (the-as uint 3))
              (let ((a2-2 (find-poly-containing-point-local gp-0 s3-1)))
                (cond
                  (a2-2
                    (clamp-vector-to-mesh-cross-gaps
                      gp-0
                      (-> s3-1 point)
                      a2-2
                      arg0
                      2048.0
                      #f
                      (the-as clamp-travel-vector-to-mesh-return-info #f)
                      )
                    (let ((v1-7 arg0))
                      (.lvf vf1 (&-> arg0 quad))
                      (let ((f0-2 (-> pp clock frames-per-second)))
                        (.mov at-1 f0-2)
                        )
                      (.mov vf2 at-1)
                      (.mov.vf.w vf1 vf0)
                      (.mul.x.vf.xyz vf1 vf1 vf2)
                      (.svf (&-> v1-7 quad) vf1)
                      )
                    )
                  (else
                    (set! (-> arg0 x) (* (-> arg0 x) (- arg4)))
                    (set! (-> arg0 y) (* (-> arg0 y) (-> pp clock frames-per-second)))
                    (set! (-> arg0 z) (* (-> arg0 z) (- arg4)))
                    )
                  )
                )
              )
            gp-0
            )
          (else
            (set! (-> arg0 quad) (-> arg2 quad))
            (the-as nav-mesh #f)
            )
          )
        )
      )
    )
  )

(defmethod project-point-to-nav-mesh ((this entity-actor) (arg0 vector) (arg1 vector) (arg2 nav-poly) (arg3 float))
  (local-vars (sv-16 vector))
  (let ((gp-0 (nav-mesh-from-res-tag this 'nav-mesh-actor 0)))
    (cond
      (gp-0
        (set! sv-16 arg0)
        (let ((s5-1 (new 'stack-no-clear 'nav-find-poly-parms)))
          (set! (-> s5-1 poly) arg2)
          (vector-! (-> s5-1 point) arg1 (-> gp-0 bounds))
          (when (or (not (-> s5-1 poly)) (not (point-in-poly? gp-0 (-> s5-1 poly) (-> s5-1 point))))
            (set! (-> s5-1 y-threshold) arg3)
            (set! (-> s5-1 ignore) (the-as uint 3))
            (find-nearest-poly-to-point-local gp-0 s5-1)
            (when (-> s5-1 poly)
              (project-point-into-poly-2d gp-0 (-> s5-1 poly) sv-16 (-> s5-1 point))
              (vector+! sv-16 sv-16 (-> gp-0 bounds))
              )
            )
          (-> s5-1 poly)
          )
        )
      (else
        (set! (-> arg0 quad) (-> arg1 quad))
        (the-as nav-poly #f)
        )
      )
    )
  )

;; WARN: Return type mismatch uint vs int.
(defmethod length ((this nav-mesh))
  (the-as int (-> this poly-count))
  )

(defmethod debug-draw-poly ((this nav-mesh) (arg0 nav-poly) (arg1 rgba))
  (let ((gp-0 (new 'stack-no-clear 'inline-array 'vector 3)))
    (set! (-> gp-0 0 quad) (-> this bounds quad))
    (if (logtest? (-> arg0 pat) 7)
        (+! (-> gp-0 0 y) 409.6)
        )
    (let ((v1-7 (the-as int (+ (-> arg0 vertex-count) -1))))
      (dotimes (s2-0 (the-as int (-> arg0 vertex-count)))
        (add-debug-line
          #t
          (bucket-id debug-no-zbuf1)
          (vector+! (-> gp-0 1) (-> gp-0 0) (-> arg0 vertex s2-0))
          (vector+! (-> gp-0 2) (-> gp-0 0) (-> arg0 vertex v1-7))
          arg1
          #f
          (the-as rgba -1)
          )
        (set! v1-7 s2-0)
        )
      )
    (when (and (logtest? (-> arg0 pat) 4) (< (-> arg0 link) (-> this link-count)))
      (poly-centroid this arg0 (-> gp-0 1))
      (let ((s5-1 (-> this link-array (-> arg0 link))))
        (add-debug-x #t (bucket-id debug-no-zbuf1) (-> gp-0 1) *color-magenta*)
        (let ((s4-1 add-debug-text-3d)
              (s3-1 #t)
              (s2-1 (bucket-id debug-no-zbuf1))
              )
          (format (clear *temp-string*) "link ~D" (-> s5-1 id))
          (s4-1
            s3-1
            (the-as bucket-id s2-1)
            *temp-string*
            (-> gp-0 1)
            (font-color pink)
            (new 'static 'vector2h :data (new 'static 'array int16 2 0 8))
            )
          )
        )
      )
    )
  0
  (none)
  )

(defmethod new-nav-control ((this nav-mesh) (arg0 process-drawable))
  (let ((gp-0 (the-as nav-control #f)))
    (dotimes (v1-0 (the-as int (-> this nav-control-count)))
      (let ((a1-2 (-> this nav-control-array v1-0)))
        (b! (-> a1-2 process) cfg-3 :delay (empty-form))
        (set! gp-0 a1-2)
        )
      (set! (-> gp-0 process) (the-as process 0))
      (set! (-> gp-0 state mesh) this)
      (b! #t cfg-8 :delay (nop!))
      (label cfg-3)
      )
    (let ((v1-3 (-> this nav-control-count)))
      (cond
        ((< v1-3 (-> this max-nav-control-count))
         (+! (-> this nav-control-count) 1)
         (set! gp-0 (-> this nav-control-array v1-3))
         (set! (-> gp-0 state mesh) this)
         )
        (else
          (format
            0
            "nav-mesh::new-nav-control:  too many users for nav-mesh ~s~%"
            (res-lump-struct (-> this entity) 'name structure)
            )
          )
        )
      )
    (label cfg-8)
    gp-0
    )
  )

(defmethod remove-nav-control ((this nav-mesh) (arg0 nav-control))
  (set! (-> arg0 process) #f)
  (let ((v1-1 (+ (-> this nav-control-count) -1)))
    (while (and (>= v1-1 0) (not (-> this nav-control-array v1-1 process)))
      (+! v1-1 -1)
      )
    (set! (-> this nav-control-count) (+ v1-1 1))
    )
  0
  (none)
  )

(defmethod add-process-drawable-to-navmesh ((this nav-mesh) (arg0 process-drawable) (arg1 symbol))
  (if arg1
      (change-to this arg0)
      (add-connection (-> this user-list) arg0 nothing arg0 #f (-> arg0 root))
      )
  0
  (none)
  )

(defmethod remove-process-drawable ((this nav-mesh) (arg0 process-drawable))
  (remove-from-process (-> this user-list) arg0)
  (let ((a1-2 (-> arg0 nav)))
    (when (nonzero? a1-2)
      (remove-nav-control this a1-2)
      (set! (-> arg0 nav) #f)
      )
    )
  0
  (none)
  )

(defmethod change-to ((this nav-mesh) (arg0 process-drawable))
  (local-vars (v1-5 symbol))
  (let ((gp-0 arg0))
    (b! (nonzero? (-> this user-list)) cfg-2 :delay (empty-form))
    (go process-drawable-art-error "nav mesh not initialized")
    (b! #t cfg-18 :delay (nop!))
    (label cfg-2)
    (let ((s3-0 (-> gp-0 nav)))
      (b! (nonzero? s3-0) cfg-4 :delay (empty-form))
      (set! s3-0 (the-as nav-control #f))
      (label cfg-4)
      (b! (not s3-0) cfg-7 :likely-delay (set! v1-5 #t))
      (set! v1-5 (!= this (-> s3-0 state mesh)))
      (label cfg-7)
      (b! (not v1-5) cfg-18 :delay (empty-form))
      (let ((s4-0 (new-nav-control this arg0)))
        (b! s4-0 cfg-12 :delay (empty-form))
        (b! (not *debug-segment*) cfg-11 :delay (empty-form))
        (format 0 "ERROR: nav-mesh::change-to: unable to allocate nav-mesh for ~s~%" gp-0)
        (label cfg-11)
        (b! #t cfg-18 :delay (nop!))
        (label cfg-12)
        (cond
          (s3-0
            (quad-copy! (the-as pointer s4-0) (the-as pointer s3-0) 18)
            (set! (-> s4-0 state mesh) this)
            (set! (-> s4-0 state nav) s4-0)
            (set! (-> s4-0 state current-poly) #f)
            (set! (-> s4-0 state virtual-current-poly) #f)
            (set! (-> s4-0 state next-poly) #f)
            (set! (-> s4-0 state user-poly) #f)
            (set! (-> s4-0 state target-poly) #f)
            (let ((s2-0 (-> s3-0 state mesh)))
              (remove-nav-control s2-0 s3-0)
              (remove-from-process (-> s2-0 user-list) gp-0)
              )
            )
          (else
            (init! s4-0 (the-as collide-shape (-> gp-0 root)))
            )
          )
        (set-nearest-y-thres! s4-0 (-> this nearest-y-threshold))
        (set! (-> gp-0 nav) s4-0)
        )
      )
    (add-connection (-> this user-list) gp-0 nothing gp-0 #t (-> gp-0 root))
    (send-event gp-0 'nav-mesh-new :from gp-0)
    )
  (label cfg-18)
  0
  (none)
  )

(defmethod link-to-other-mesh ((this nav-mesh) (arg0 nav-mesh-link))
  (when (not (-> arg0 dest-mesh))
    (let* ((s4-0 (entity-nav-mesh-by-aid (the-as actor-id (-> arg0 dest-mesh-id))))
           (v1-1 (if (type? s4-0 entity-nav-mesh)
                     s4-0
                     )
                 )
           )
      (when v1-1
        (let ((a0-3 (-> v1-1 nav-mesh))
              (v1-2 (the-as nav-mesh-link #f))
              )
          (dotimes (a1-2 (the-as int (-> a0-3 link-count)))
            (let ((a2-1 (-> a0-3 link-array a1-2)))
              (let ((a3-1 (-> arg0 id)))
                (b! (!= (-> a2-1 id) a3-1) cfg-7 :delay (empty-form))
                )
              (set! v1-2 a2-1)
              )
            (b! #t cfg-10 :delay (nop!))
            (label cfg-7)
            )
          (label cfg-10)
          (when v1-2
            (set! (-> arg0 dest-mesh) a0-3)
            (set! (-> v1-2 dest-mesh) this)
            (set! (-> arg0 dest-link-poly-id) (-> v1-2 src-switch-poly-id))
            (set! (-> arg0 dest-switch-poly-id) (-> v1-2 src-link-poly-id))
            (set! (-> v1-2 dest-link-poly-id) (-> arg0 src-switch-poly-id))
            (set! (-> v1-2 dest-switch-poly-id) (-> arg0 src-link-poly-id))
            #t
            )
          )
        )
      )
    )
  )

(defmethod unlink-mesh ((this nav-mesh) (arg0 nav-mesh-link))
  (let ((a0-1 (-> arg0 dest-mesh)))
    (when a0-1
      (let ((v1-0 (the-as nav-mesh-link #f)))
        (dotimes (a2-1 (the-as int (-> a0-1 link-count)))
          (let ((a3-1 (-> a0-1 link-array a2-1)))
            (let ((t0-1 (-> arg0 id)))
              (b! (!= (-> a3-1 id) t0-1) cfg-4 :delay (empty-form))
              )
            (set! v1-0 a3-1)
            )
          (b! #t cfg-7 :delay (nop!))
          (label cfg-4)
          )
        (label cfg-7)
        (when v1-0
          (set! (-> arg0 dest-mesh) #f)
          (set! (-> v1-0 dest-mesh) #f)
          )
        )
      )
    )
  0
  (none)
  )

(defmethod link-by-id ((this nav-mesh) (arg0 uint))
  "arg1 is a [[nav-mesh-link]] `id`"
  (let ((v1-0 (the-as nav-mesh-link #f)))
    (dotimes (a2-0 (the-as int (-> this link-count)))
      (let ((a3-1 (-> this link-array a2-0)))
        (b! (!= (-> a3-1 id) arg0) cfg-3 :delay (empty-form))
        (set! v1-0 a3-1)
        )
      (b! #t cfg-6 :delay (nop!))
      (label cfg-3)
      )
    (label cfg-6)
    (if v1-0
        (link-to-other-mesh this v1-0)
        )
    )
  )

(defmethod unlink-by-id ((this nav-mesh) (arg0 uint))
  "arg1 is a [[nav-mesh-link]] `id`"
  (let ((v1-0 (the-as nav-mesh-link #f)))
    (dotimes (a2-0 (the-as int (-> this link-count)))
      (let ((a3-1 (-> this link-array a2-0)))
        (b! (!= (-> a3-1 id) arg0) cfg-3 :delay (empty-form))
        (set! v1-0 a3-1)
        )
      (b! #t cfg-6 :delay (nop!))
      (label cfg-3)
      )
    (label cfg-6)
    (when v1-0
      (unlink-mesh this v1-0)
      #t
      )
    )
  )

(defmethod init-from-entity ((this nav-mesh) (arg0 entity-nav-mesh))
  "Initialize this mesh from an entity."
  (local-vars (sv-16 res-tag))
  (set! (-> this entity) arg0)
  (set! (-> this work) *nav-mesh-work*)
  (set! sv-16 (new 'static 'res-tag))
  (let ((v1-2 (res-lump-data arg0 'nav-mesh-sphere pointer :tag-ptr (& sv-16))))
    (when v1-2
      (set! (-> this static-sphere-count) (-> sv-16 elt-count))
      (set! (-> this static-sphere) (the-as (inline-array sphere) v1-2))
      )
    )
  (set! (-> this nearest-y-threshold) (res-lump-float arg0 'nearest-y-threshold :default 40960.0))
  (set! (-> this flags) (nav-mesh-flag))
  (set! (-> this water-max-height) (res-lump-float arg0 'water-max-height :default 8192.0))
  (let ((s5-1 (res-lump-value arg0 'nav-max-users uint128 :default (the-as uint128 64) :time -1000000000.0)))
    (set! (-> this user-list) (new 'loading-level 'engine 'nav-engine (the-as int s5-1) connection))
    (set! (-> this nav-control-array)
          (the-as (inline-array nav-control) (malloc 'loading-level (* 288 (the-as int s5-1))))
          )
    (set! (-> this nav-control-count) (the-as uint 0))
    (set! (-> this max-nav-control-count) (the-as uint s5-1))
    (set! (-> this sphere-hash)
          (new 'loading-level 'sphere-hash 4096 (the-as int (+ s5-1 (-> this static-sphere-count))))
          )
    )
  (if (nonzero? (-> this poly-hash))
      (set! (-> this poly-hash work) *grid-hash-work*)
      )
  (initialize-mesh! this)
  0
  (none)
  )

(defmethod handle-birth ((this nav-mesh))
  "Handle the parent nav-mesh-entity birth."
  (dotimes (s5-0 (the-as int (-> this link-count)))
    (let ((a1-0 (-> this link-array s5-0)))
      (if (not (-> a1-0 dest-mesh))
          (link-to-other-mesh this a1-0)
          )
      )
    )
  0
  (none)
  )

(defmethod handle-kill ((this nav-mesh))
  "Handle the parent nav-mesh-entity kill."
  (when (nonzero? (-> this user-list))
    (countdown (s5-0 (-> this nav-control-count))
      (let* ((v1-3 (-> this nav-control-array s5-0))
             (s4-0 (-> v1-3 process))
             )
        (when s4-0
          (if (not (send-event (-> v1-3 process) 'nav-mesh-kill))
              (format 0 "ERROR: object ~A did not accept nav-mesh kill~%" s4-0)
              )
          )
        )
      )
    (remove-all (-> this user-list))
    (dotimes (s5-1 (the-as int (-> this link-count)))
      (let ((a1-2 (-> this link-array s5-1)))
        (if (-> a1-2 dest-mesh)
            (unlink-mesh this a1-2)
            )
        )
      )
    )
  0
  (none)
  )

(deftype nav-engine-spr-buffer (structure)
  ((mem-addr   (pointer nav-mesh))
   (mem-nav    uint32  :overlay-at mem-addr)
   (spr-addr   (inline-array nav-control))
   (spr-nav    uint32  :overlay-at spr-addr)
   (q-size     uint32)
   (i-nav      uint8)
   (done       int8)
   (nav-count  int8)
   (i-pass     int8)
   )
  :pack-me
  )

(defmethod inspect ((this nav-engine-spr-buffer))
  (when (not this)
    (set! this this)
    (goto cfg-4)
    )
  (format #t "[~8x] ~A~%" this 'nav-engine-spr-buffer)
  (format #t "~1Tmem-addr: ~D~%" (-> this mem-addr))
  (format #t "~1Tmem-nav: #x~X~%" (-> this mem-addr))
  (format #t "~1Tspr-addr: ~D~%" (-> this spr-addr))
  (format #t "~1Tspr-nav: #x~X~%" (-> this spr-addr))
  (format #t "~1Tq-size: ~D~%" (-> this q-size))
  (format #t "~1Ti-nav: ~D~%" (-> this i-nav))
  (format #t "~1Tdone: ~D~%" (-> this done))
  (format #t "~1Tnav-count: ~D~%" (-> this nav-count))
  (format #t "~1Ti-pass: ~D~%" (-> this i-pass))
  (label cfg-4)
  this
  )

(deftype nav-engine (structure)
  ((spr-addr               uint32)
   (nav-work-addr          uint32)
   (nav-mesh-addr          nav-mesh)
   (poly-array-addr        uint32)
   (hash-sphere-addr       uint32)
   (hash-buckets-addr      uint32)
   (buf-nav-control-count  int8)
   (max-pass-count         int8)
   (output-sphere-hash     uint8)
   (work-buf-array         nav-engine-spr-buffer  3 :inline)
   (spr-work               nav-mesh-work          :overlay-at nav-work-addr)
   (mem-work               nav-mesh-work)
   (spr-mesh               nav-mesh               :overlay-at nav-mesh-addr)
   (mem-mesh               nav-mesh)
   (spr-poly-array         uint32                 :overlay-at poly-array-addr)
   (mem-poly-array         (inline-array nav-poly))
   (hash-sphere-list       uint32                 :overlay-at hash-sphere-addr)
   (hash-buckets           uint32                 :overlay-at hash-buckets-addr)
   (to-spr-wait            uint32)
   (from-spr-wait          uint32)
   )
  (:methods
    (inc-spr-addr! (_type_ uint) uint)
    (lay-out-spad-memory (_type_ nav-mesh) none)
    (set-up-mem-work (_type_) none)
    (add-spheres-from-mesh-user-list (_type_ sphere-hash nav-mesh) none)
    (add-all-spheres (_type_) none)
    (do-sphere-lookups (_type_) none)
    (update-nav-controls-pipelined-in-spr (_type_) none)
    (update-nav-controls-in-spr (_type_) none)
    (upload-nav-to-spr (_type_ nav-engine-spr-buffer) none)
    (download-nav-from-spr (_type_ nav-engine-spr-buffer) none)
    (do-callbacks (_type_ nav-engine-spr-buffer) none)
    (reloc-ptrs-to-spad (_type_ nav-engine-spr-buffer) none)
    (reloc-ptrs-to-mem (_type_ nav-engine-spr-buffer) none)
    )
  )

(defmethod inspect ((this nav-engine))
  (when (not this)
    (set! this this)
    (goto cfg-4)
    )
  (format #t "[~8x] ~A~%" this 'nav-engine)
  (format #t "~1Tspr-addr: ~D~%" (-> this spr-addr))
  (format #t "~1Tnav-work-addr: ~D~%" (-> this nav-work-addr))
  (format #t "~1Tnav-mesh-addr: ~D~%" (-> this nav-mesh-addr))
  (format #t "~1Tpoly-array-addr: ~D~%" (-> this poly-array-addr))
  (format #t "~1Thash-sphere-addr: ~D~%" (-> this hash-sphere-addr))
  (format #t "~1Thash-buckets-addr: ~D~%" (-> this hash-buckets-addr))
  (format #t "~1Tbuf-nav-control-count: ~D~%" (-> this buf-nav-control-count))
  (format #t "~1Tmax-pass-count: ~D~%" (-> this max-pass-count))
  (format #t "~1Toutput-sphere-hash: ~D~%" (-> this output-sphere-hash))
  (format #t "~1Twork-buf-array[3] @ #x~X~%" (-> this work-buf-array))
  (format #t "~1Tspr-work: #<nav-mesh-work @ #x~X>~%" (-> this nav-work-addr))
  (format #t "~1Tmem-work: #<nav-mesh-work @ #x~X>~%" (-> this mem-work))
  (format #t "~1Tspr-mesh: ~A~%" (-> this nav-mesh-addr))
  (format #t "~1Tmem-mesh: ~A~%" (-> this mem-mesh))
  (format #t "~1Tspr-poly-array: #x~X~%" (-> this poly-array-addr))
  (format #t "~1Tmem-poly-array: #x~X~%" (-> this mem-poly-array))
  (format #t "~1Thash-sphere-list: #x~X~%" (-> this hash-sphere-addr))
  (format #t "~1Thash-buckets: #x~X~%" (-> this hash-buckets-addr))
  (format #t "~1Tto-spr-wait: ~D~%" (-> this to-spr-wait))
  (format #t "~1Tfrom-spr-wait: ~D~%" (-> this from-spr-wait))
  (label cfg-4)
  this
  )

(defmethod inc-spr-addr! ((this nav-engine) (arg0 uint))
  "Adds the given integer to `spr-addr` and returns it"
  (let ((v0-0 (-> this spr-addr)))
    (+! (-> this spr-addr) arg0)
    v0-0
    )
  )

(defmethod lay-out-spad-memory ((this nav-engine) (arg0 nav-mesh))
  (let ((s5-0 0))
    ;; og:preserve-this scratchpad
    (set! (-> this spr-addr) (scratchpad-object uint :offset #x60))
    (let* ((v1-1 this)
           (a1-1 320)
           (a0-1 (-> v1-1 spr-addr))
           )
      (+! (-> v1-1 spr-addr) a1-1)
      (set! (-> this nav-work-addr) a0-1)
      )
    (let* ((v1-2 this)
           (a1-3 112)
           (a0-2 (-> v1-2 spr-addr))
           )
      (+! (-> v1-2 spr-addr) a1-3)
      (set! (-> this nav-mesh-addr) (the-as nav-mesh a0-2))
      )
    (if (and (= (-> *nav-mesh-work* polys-in-scratch) 1) (< (-> arg0 poly-count) (the-as uint 64)))
        (set! s5-0 (the-as int (-> arg0 poly-count)))
        )
    (let* ((v1-10 this)
           (a1-5 (* s5-0 64))
           (a0-4 (-> v1-10 spr-addr))
           )
      (+! (-> v1-10 spr-addr) a1-5)
      (set! (-> this poly-array-addr) a0-4)
      )
    (let* ((v1-11 this)
           (a1-7 (* (-> arg0 sphere-hash max-object-count) 16))
           (a0-7 (-> v1-11 spr-addr))
           )
      (+! (-> v1-11 spr-addr) a1-7)
      (set! (-> this hash-sphere-addr) a0-7)
      )
    (let* ((v1-12 this)
           (a1-9 0)
           (a0-8 (-> v1-12 spr-addr))
           )
      (+! (-> v1-12 spr-addr) a1-9)
      (set! (-> this hash-buckets-addr) a0-8)
      )
    (set! (-> this buf-nav-control-count) 7)
    (dotimes (v1-14 3)
      (let ((a0-11 (-> this work-buf-array v1-14)))
        (let* ((a1-11 this)
               (a3-0 2048)
               (a2-5 (-> a1-11 spr-addr))
               )
          (+! (-> a1-11 spr-addr) a3-0)
          (set! (-> a0-11 spr-addr) (the-as (inline-array nav-control) a2-5))
          )
        (set! (-> a0-11 mem-addr) (the-as (pointer nav-mesh) 0))
        (set! (-> a0-11 q-size) (the-as uint 0))
        (set! (-> a0-11 nav-count) 0)
        (set! (-> a0-11 i-pass) -1)
        )
      )
    (set! (-> this output-sphere-hash) (the-as uint 0))
    (set! (-> this mem-mesh) arg0)
    (cond
      ((= (-> *nav-mesh-work* mesh-struct-in-scratch) 1)
       (set! (-> this nav-mesh-addr) (the-as nav-mesh (&-> (-> this nav-mesh-addr) poly-array)))
       (mem-copy! (&-> (-> this nav-mesh-addr) type) (&-> arg0 type) 112)
       )
      (else
        (set! (-> this nav-mesh-addr) arg0)
        )
      )
    (set! (-> this mem-work) (-> arg0 work))
    (if (= (-> *nav-mesh-work* work-struct-in-scratch) 1)
        (quad-copy! (the-as pointer (-> this nav-work-addr)) (the-as pointer (-> this mem-work)) 20)
        (set! (-> this nav-work-addr) (the-as uint (-> arg0 work)))
        )
    (set! (-> this nav-mesh-addr work) (the-as nav-mesh-work (-> this nav-work-addr)))
    (set! (-> this mem-poly-array) (-> arg0 poly-array))
    (when (> s5-0 0)
      (quad-copy! (the-as pointer (-> this poly-array-addr)) (the-as pointer (-> this mem-poly-array)) (* s5-0 4))
      (set! (-> this nav-mesh-addr poly-array) (the-as (inline-array nav-poly) (-> this poly-array-addr)))
      )
    )
  0
  (none)
  )

(defmethod set-up-mem-work ((this nav-engine))
  (let ((v1-0 (-> this mem-mesh)))
    (set! (-> v1-0 poly-array) (-> this mem-poly-array))
    (set! (-> v1-0 work) (-> this mem-work))
    )
  0
  (none)
  )

(defmethod add-spheres-from-mesh-user-list ((this nav-engine) (arg0 sphere-hash) (arg1 nav-mesh))
  (countdown (s3-0 (-> arg1 static-sphere-count))
    (add-a-sphere-with-flag arg0 (-> arg1 static-sphere s3-0) 64)
    )
  (let* ((s4-1 (-> arg1 user-list))
         (v1-6 (-> s4-1 alive-list next0))
         (s3-1 (-> (the-as connection v1-6) next0))
         )
    (while (!= v1-6 (-> s4-1 alive-list-end))
      (let ((a0-4 (-> (the-as connection v1-6) param1))
            (s2-0 (the-as object (-> (the-as connection v1-6) param3)))
            )
        (cond
          ((-> (the-as connection v1-6) param2)
           (let ((s1-0 (-> (the-as process-focusable a0-4) nav)))
             (set! (-> s1-0 sec-per-frame) (-> (the-as process-focusable a0-4) clock seconds-per-frame))
             (set! (-> s1-0 root-nav-sphere quad) (-> (the-as collide-shape s2-0) trans quad))
             (set! (-> s1-0 root-nav-sphere w) (-> (the-as collide-shape s2-0) nav-radius))
             (if (logtest? (-> s1-0 flags) (nav-control-flag output-sphere-hash))
                 (set! (-> this output-sphere-hash) (the-as uint 1))
                 )
             (if (logtest? (-> (the-as collide-shape s2-0) nav-flags) (nav-flags has-root-sphere))
                 (set! (-> s1-0 root-sphere-id)
                       (the-as uint (add-a-sphere-with-flag
                                      arg0
                                      (-> s1-0 root-nav-sphere)
                                      (the-as int (-> (the-as collide-shape s2-0) backup-collide-as))
                                      )
                               )
                       )
                 )
             (if (logtest? (-> (the-as collide-shape s2-0) nav-flags) (nav-flags has-extra-sphere))
                 (add-a-sphere-with-flag
                   arg0
                   (-> s1-0 extra-nav-sphere)
                   (the-as int (-> (the-as collide-shape s2-0) backup-collide-as))
                   )
                 )
             )
           )
          (else
            (when (logtest? (-> (the-as collide-shape s2-0) nav-flags) (nav-flags has-root-sphere))
              (let ((a1-5 (new 'stack-no-clear 'vector)))
                (set! (-> a1-5 quad) (-> (the-as collide-shape s2-0) trans quad))
                (set! (-> a1-5 w) (-> (the-as collide-shape s2-0) nav-radius))
                (add-a-sphere-with-flag arg0 a1-5 (the-as int (-> (the-as collide-shape s2-0) backup-collide-as)))
                )
              )
            )
          )
        (when (logtest? (-> (the-as collide-shape s2-0) nav-flags) (nav-flags has-child-spheres))
          (let ((s2-1 (-> (the-as collide-shape s2-0) root-prim))
                (s1-1 1)
                )
            (when (= (-> s2-1 prim-core prim-type) (prim-type group))
              (let ((v1-35 s2-1))
                (set! s2-1 (-> (the-as collide-shape-prim-group v1-35) child 0))
                (set! s1-1 (the-as int (-> v1-35 specific 0)))
                )
              )
            (while (nonzero? s1-1)
              (+! s1-1 -1)
              (when (and (logtest? (collide-action nav-sphere) (-> s2-1 prim-core action))
                         (= (-> s2-1 prim-core prim-type) (prim-type sphere))
                         )
                (let ((a1-6 (new 'stack-no-clear 'vector)))
                  (set! (-> a1-6 quad) (-> s2-1 prim-core world-sphere quad))
                  (set! (-> a1-6 w) (-> (the-as collide-shape-prim-sphere s2-1) nav-radius))
                  (add-a-sphere-with-flag arg0 a1-6 (the-as int (-> s2-1 prim-core collide-as)))
                  )
                )
              (&+! s2-1 80)
              )
            )
          )
        )
      (set! v1-6 s3-1)
      (set! s3-1 (-> s3-1 next0))
      )
    )
  0
  (none)
  )

(defmethod add-all-spheres ((this nav-engine))
  (let ((s4-0 (-> this nav-mesh-addr))
        (gp-0 (-> this nav-mesh-addr sphere-hash))
        )
    (clear-objects! gp-0)
    (set! (-> gp-0 bucket-array) (the-as (pointer grid-hash-word) (-> this hash-buckets-addr)))
    (set! (-> gp-0 sphere-array) (the-as (inline-array sphere) (-> this hash-sphere-addr)))
    (when *target*
      (let ((a1-0 (new 'stack-no-clear 'nav-vertex)))
        (let ((v1-8 (-> *target* control)))
          (set! (-> a1-0 quad) (-> v1-8 trans quad))
          (set! (-> a1-0 w) (-> v1-8 nav-radius))
          )
        (add-a-sphere-with-flag gp-0 a1-0 2)
        )
      )
    (add-spheres-from-mesh-user-list this gp-0 s4-0)
    (let ((s3-0 (the-as nav-mesh (-> s4-0 next-nav-mesh))))
      (while (and s3-0 (nonzero? s3-0))
        (add-spheres-from-mesh-user-list this gp-0 s3-0)
        (set! s3-0 (the-as nav-mesh (-> s3-0 next-nav-mesh)))
        )
      )
    (let ((s4-1 (the-as nav-mesh (-> s4-0 prev-nav-mesh))))
      (while (and s4-1 (nonzero? s4-1))
        (add-spheres-from-mesh-user-list this gp-0 s4-1)
        (set! s4-1 (the-as nav-mesh (-> s4-1 prev-nav-mesh)))
        )
      )
    (update-from-spheres gp-0)
    )
  0
  (none)
  )

(defmethod do-sphere-lookups ((this nav-engine))
  (let ((s5-0 (-> this nav-mesh-addr)))
    (dotimes (s4-0 (the-as int (-> s5-0 nav-control-count)))
      (let ((a0-3 (-> s5-0 nav-control-array s4-0)))
        (when (-> a0-3 process)
          (set! (-> a0-3 sphere-count) 0)
          (set! (-> a0-3 state mesh) (-> this nav-mesh-addr))
          (set! (-> this mem-work nav) (the-as basic a0-3))
          (find-sphere-ids-from-sphere-hash a0-3 #f)
          (set! (-> this mem-work nav) #f)
          )
        )
      )
    )
  0
  (none)
  )

(def-mips2c nav-dma-send-to-spr-no-flush (function pointer pointer int none))

(def-mips2c nav-dma-send-from-spr-no-flush (function pointer pointer int none))

(defun inc-mod3 ((arg0 int))
  "Increments and returns the provided [[int]], if the value exceeds `2`, wrap back to `0`"
  (local-vars (v0-1 int) (v1-1 int))
  (let ((v0-0 (+ arg0 1)))
    (let ((v1-0 2))
      (set-on-less-than v1-1 v1-0 v0-0)
      )
    (move-if-not-zero v0-1 0 v1-1 v0-0)
    )
  v0-1
  )

(def-mips2c nav-state-patch-pointers (function nav-state int none))

(defmethod-mips2c "(method 17 nav-engine)" 17 nav-engine)

(defmethod-mips2c "(method 18 nav-engine)" 18 nav-engine)

(defmethod do-callbacks ((this nav-engine) (arg0 nav-engine-spr-buffer))
  (local-vars (sv-16 nav-callback-info))
  (with-pp
    (dotimes (s4-0 (-> arg0 nav-count))
      (let* ((a1-1 (-> arg0 spr-addr s4-0))
             (a0-3 (-> a1-1 process))
             )
        (set! sv-16 (-> a1-1 callback-info))
        (when a0-3
          (set! (-> a1-1 state nav) a1-1)
          (when (and (logtest? (-> a1-1 flags) (nav-control-flag kernel-run)) sv-16)
            (let ((s3-0 pp))
              (set! pp a0-3)
              (set! (-> this mem-mesh work nav) (the-as basic a1-1))
              (let ((v1-10 (-> sv-16 callback-count)))
                (set! (-> this max-pass-count) (max (-> this max-pass-count) v1-10))
                (if (< (-> arg0 i-pass) v1-10)
                    ((-> sv-16 callback-array (-> arg0 i-pass)) a0-3 a1-1)
                    )
                )
              (set! pp s3-0)
              )
            (set! (-> this mem-mesh work nav) #f)
            )
          )
        )
      )
    0
    (none)
    )
  )

(defmethod-mips2c "(method 20 nav-engine)" 20 nav-engine)

(defmethod-mips2c "(method 21 nav-engine)" 21 nav-engine)

(defmethod update-nav-controls-pipelined-in-spr ((this nav-engine))
  (local-vars
    (v1-33 int)
    (v1-45 int)
    (v1-66 int)
    (a0-14 int)
    (a0-19 int)
    (a0-26 int)
    (sv-16 symbol)
    (sv-24 int)
    (sv-32 int)
    (sv-40 uint)
    (sv-44 (inline-array nav-control))
    (sv-48 nav-engine-spr-buffer)
    )
  (flush-cache 0)
  (set! (-> this max-pass-count) 3)
  (set! sv-16 (the-as symbol #f))
  (set! sv-24 0)
  (set! sv-32 0)
  (set! sv-40 (-> this nav-mesh-addr nav-control-count))
  (set! sv-44 (-> this nav-mesh-addr nav-control-array))
  (let ((s5-0 2)
        (s3-0 1)
        (s4-0 0)
        )
    (while (not sv-16)
      (let ((s2-0 (-> this work-buf-array s5-0)))
        (set! (-> s2-0 i-nav) (the-as uint sv-32))
        (set! (-> s2-0 nav-count) (min (-> this buf-nav-control-count) (the-as int (- sv-40 (the-as uint sv-32)))))
        (set! (-> s2-0 i-pass) sv-24)
        (set! (-> s2-0 mem-addr) (the-as (pointer nav-mesh) (-> sv-44 sv-32)))
        (set! (-> s2-0 q-size) (the-as uint (* 18 (-> s2-0 nav-count))))
        (set! (-> s2-0 done) 0)
        (when (>= sv-24 (-> this max-pass-count))
          (set! (-> s2-0 nav-count) 0)
          0
          )
        (if (> (-> s2-0 nav-count) 0)
            (upload-nav-to-spr this s2-0)
            (dma-sync (the-as pointer #x1000d400) 0 0)
            )
        (set! sv-32 (+ sv-32 (-> s2-0 nav-count)))
        (when (>= sv-32 (the-as int sv-40))
          (set! sv-32 0)
          (set! sv-24 (+ sv-24 1))
          (if (= sv-24 (-> this max-pass-count))
              (set! (-> s2-0 done) 1)
              )
          )
        )
      (let ((v1-32 (+ s5-0 1)))
        (let ((a0-13 2))
          (set-on-less-than a0-14 a0-13 v1-32)
          )
        (move-if-not-zero v1-33 0 a0-14 v1-32)
        )
      (set! s5-0 v1-33)
      (let ((s2-1 (-> this work-buf-array s4-0)))
        (when (> (-> s2-1 nav-count) 0)
          (download-nav-from-spr this s2-1)
          (when (= (-> s2-1 done) 1)
            (dma-sync (the-as pointer #x1000d000) 0 0)
            (set! sv-16 #t)
            )
          )
        )
      (let ((v1-44 (+ s4-0 1)))
        (let ((a0-18 2))
          (set-on-less-than a0-19 a0-18 v1-44)
          )
        (move-if-not-zero v1-45 0 a0-19 v1-44)
        )
      (set! s4-0 v1-45)
      (set! sv-48 (-> this work-buf-array s3-0))
      (when (> (-> sv-48 nav-count) 0)
        (if (zero? (-> sv-48 i-pass))
            (reloc-ptrs-to-spad this sv-48)
            )
        (do-callbacks this sv-48)
        (if (= (-> sv-48 i-pass) (+ (-> this max-pass-count) -1))
            (reloc-ptrs-to-mem this sv-48)
            )
        )
      (let ((v1-65 (+ s3-0 1)))
        (let ((a0-25 2))
          (set-on-less-than a0-26 a0-25 v1-65)
          )
        (move-if-not-zero v1-66 0 a0-26 v1-65)
        )
      (set! s3-0 v1-66)
      )
    )
  0
  (none)
  )

(defmethod update-nav-controls-in-spr ((this nav-engine))
  (flush-cache 0)
  (set! (-> this max-pass-count) 1)
  (let ((gp-0 (the-as object (-> this work-buf-array))))
    (set! (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 i-nav) (the-as uint 0))
    (set! (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 nav-count)
          (the-as int (-> this nav-mesh-addr nav-control-count))
          )
    (set! (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 i-pass) 0)
    (set! (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 mem-addr)
          (the-as (pointer nav-mesh) (-> this nav-mesh-addr nav-control-array))
          )
    (set! (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 q-size)
          (the-as uint (* 18 (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 nav-count)))
          )
    (set! (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 done) 0)
    (when (> (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 nav-count) 0)
      (upload-nav-to-spr this (the-as nav-engine-spr-buffer gp-0))
      (dma-sync (the-as pointer #x1000d400) 0 0)
      (reloc-ptrs-to-spad this (the-as nav-engine-spr-buffer gp-0))
      (while (< (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 i-pass) (-> this max-pass-count))
        (do-callbacks this (the-as nav-engine-spr-buffer gp-0))
        (+! (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 i-pass) 1)
        )
      (reloc-ptrs-to-mem this (the-as nav-engine-spr-buffer gp-0))
      (dotimes (s4-0 (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 nav-count))
        (let ((a2-1 (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 spr-addr s4-0 state mesh)))
          ;; og:preserve-this scratchpad
          (when (in-scratchpad? a2-1)
            (format 0 "nav-engine::update-nav-controls-in-spr: (pre-dma) bad mesh pointer found (#x0~x)~%" a2-1)
            (break!)
            0
            )
          )
        )
      (download-nav-from-spr this (the-as nav-engine-spr-buffer gp-0))
      (dma-sync (the-as pointer #x1000d000) 0 0)
      (dotimes (s5-1 (-> (the-as (inline-array nav-engine-spr-buffer) gp-0) 0 nav-count))
        (let ((a2-3 (-> (&+ (-> (the-as nav-engine-spr-buffer gp-0) mem-addr) (* 288 s5-1)) 31)))
          ;; og:preserve-this scratchpad
          (when (in-scratchpad? a2-3)
            (format 0 "nav-engine::update-nav-controls-in-spr: (post-dma) bad mesh pointer found (#x0~x)~%" a2-3)
            (break!)
            0
            )
          )
        )
      )
    )
  0
  (none)
  )

(defmethod update-navigation ((this nav-mesh))
  (local-vars (sp-0 int))
  (when (zero? (-> this next-nav-mesh))
    (set! (-> this next-nav-mesh) (the-as surface (nav-mesh-from-res-tag (-> this entity) 'next-actor 0)))
    (set! (-> this prev-nav-mesh) (the-as surface (nav-mesh-from-res-tag (-> this entity) 'prev-actor 0)))
    )
  (when (> (-> this nav-control-count) 0)
    (the-as none sp-0)
    (set! sp-0 #x70003fc0)
    (set! (-> this work mesh) this)
    ;; og:preserve-this scratchpad
    (let ((s4-0 (scratchpad-object nav-engine)))
      (lay-out-spad-memory s4-0 this)
      (add-all-spheres s4-0)
      (do-sphere-lookups s4-0)
      (when (nonzero? (-> s4-0 output-sphere-hash))
        (let ((s3-0 (-> s4-0 nav-mesh-addr sphere-hash)))
          (quad-copy! (-> s3-0 mem-bucket-array) (-> s3-0 bucket-array) (/ (-> s3-0 bucket-memory-size) 16))
          (quad-copy!
            (the-as pointer (-> s3-0 mem-sphere-array))
            (the-as pointer (-> s3-0 sphere-array))
            (-> s3-0 object-count)
            )
          (set! (-> s3-0 bucket-array) (-> s3-0 mem-bucket-array))
          (set! (-> s3-0 sphere-array) (the-as (inline-array sphere) (-> s3-0 mem-sphere-array)))
          )
        )
      (if (< (the-as uint (* 3 (-> s4-0 buf-nav-control-count))) (-> this nav-control-count))
          (update-nav-controls-pipelined-in-spr s4-0)
          (update-nav-controls-in-spr s4-0)
          )
      (set-up-mem-work s4-0)
      )
    )
  0
  (none)
  )

(defmethod debug-draw ((this nav-mesh))
  (local-vars (sv-32 vector) (sv-36 int))
  (set! sv-32 (new 'stack-no-clear 'vector))
  (set! sv-36 16)
  (add-debug-sphere
    (logtest? sv-36 4)
    (bucket-id debug2)
    (-> this bounds)
    (-> this bounds w)
    (new 'static 'rgba :r #xff :g #xff :a #x20)
    )
  (add-debug-vector #t (bucket-id debug-no-zbuf1) (-> this bounds) *x-vector* (meters 1) *color-red*)
  (add-debug-vector #t (bucket-id debug-no-zbuf1) (-> this bounds) *z-vector* (meters 1) *color-blue*)
  (when (logtest? sv-36 16)
    (dotimes (s5-0 (the-as int (-> this static-sphere-count)))
      (add-debug-sphere
        #t
        (bucket-id debug2)
        (-> this static-sphere s5-0)
        (-> this static-sphere s5-0 r)
        *color-light-blue*
        )
      (let ((s4-0 add-debug-text-3d)
            (s3-0 #t)
            (s2-0 (bucket-id debug-no-zbuf1))
            )
        (format (clear *temp-string*) "~D" s5-0)
        (s4-0
          s3-0
          (the-as bucket-id s2-0)
          *temp-string*
          (-> this static-sphere s5-0)
          (font-color cyan)
          (the-as vector2h #f)
          )
        )
      )
    (dotimes (s5-1 (the-as int (-> this poly-count)))
      (let ((s4-1 (-> this poly-array s5-1)))
        (debug-draw-poly this s4-1 (cond
                                     ((logtest? (-> s4-1 pat) 1)
                                      *color-black*
                                      )
                                     ((logtest? (-> s4-1 pat) 2)
                                      *color-gray*
                                      )
                                     ((logtest? (-> s4-1 pat) 4)
                                      (if (-> this link-array (-> s4-1 link) dest-mesh)
                                          *color-green*
                                          *color-light-red*
                                          )
                                      )
                                     (else
                                       *color-cyan*
                                       )
                                     )
                         )
        (when (logtest? sv-36 32)
          (let ((s3-1 add-debug-text-3d)
                (s2-1 #t)
                (s1-1 (bucket-id debug-no-zbuf1))
                )
            (format (clear *temp-string*) "~D" (-> s4-1 id))
            (s3-1
              s2-1
              (the-as bucket-id s1-1)
              *temp-string*
              (poly-centroid this s4-1 sv-32)
              (font-color cyan)
              (the-as vector2h #f)
              )
            )
          )
        )
      )
    )
  0
  (none)
  )

(defmethod poly-centroid-local ((this nav-mesh) (arg0 nav-poly) (arg1 vector))
  (rlet ((vf0 :class vf))
    (init-vf0-vector)
    (let ((v1-0 (new 'stack-no-clear 'nav-vertex)))
      (.svf (&-> v1-0 quad) vf0)
      (dotimes (a0-2 (the-as int (-> arg0 vertex-count)))
        (vector+! (the-as vector v1-0) (the-as vector v1-0) (-> arg0 vertex a0-2))
        )
      (vector-float*! arg1 (the-as vector v1-0) (/ 1.0 (the float (-> arg0 vertex-count))))
      )
    )
  )

(defmethod poly-centroid ((this nav-mesh) (arg0 nav-poly) (arg1 vector))
  (poly-centroid-local this arg0 arg1)
  (vector+! arg1 arg1 (-> this bounds))
  )

(defun vu-point-triangle-intersection? ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 vector))
  (local-vars (v1-0 float) (v1-1 int) (v1-3 int) (a0-1 float) (a0-2 int) (a0-4 int) (a1-1 float) (a1-2 int))
  (rlet ((acc :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)
         (vf9 :class vf)
         )
    (.lvf vf1 (&-> arg1 quad))
    (.lvf vf2 (&-> arg2 quad))
    (.sub.vf.yw vf1 vf1 vf1)
    (.lvf vf3 (&-> arg3 quad))
    (.sub.vf.yw vf2 vf2 vf2)
    (.lvf vf12 (&-> arg0 quad))
    (.sub.vf.yw vf3 vf3 vf3)
    (.sub.vf vf4 vf2 vf1)
    (.sub.vf vf9 vf1 vf12)
    (.sub.vf vf5 vf3 vf2)
    (.sub.vf vf10 vf2 vf12)
    (.sub.vf vf6 vf1 vf3)
    (.sub.vf vf11 vf3 vf12)
    (.outer.product.a.vf acc vf9 vf4)
    (.outer.product.b.vf vf13 vf4 vf9 acc)
    (.outer.product.a.vf acc vf10 vf5)
    (.outer.product.b.vf vf14 vf5 vf10 acc)
    (.outer.product.a.vf acc vf11 vf6)
    (.outer.product.b.vf vf15 vf6 vf11 acc)
    (.mov v1-0 vf13)
    (.mov a1-1 vf14)
    (.mov a0-1 vf15)
    (set-on-less-than v1-1 v1-0 0)
    (set-on-less-than a1-2 a1-1 0)
    (set-on-less-than a0-2 a0-1 0)
    (let ((a0-3 (logxor a1-2 a0-2))
          (v1-2 (logxor v1-1 a1-2))
          )
      (set-on-less-than a0-4 a0-3 1)
      (set-on-less-than v1-3 v1-2 1)
      )
    (logtest? v1-3 a0-4)
    )
  )

(defun poly-in-height-range? ((arg0 nav-poly) (arg1 float) (arg2 float))
  (and (>= (+ (-> arg0 vertex3 w) arg2) arg1) (>= arg1 (- (-> arg0 vertex2 w) arg2)))
  )

(defmethod find-poly-containing-point-local ((this nav-mesh) (arg0 nav-find-poly-parms))
  (local-vars (v1-6 symbol) (v1-15 int) (a0-3 symbol) (sv-16 nav-poly))
  (let ((s4-0 (search-for-point (-> this poly-hash) (-> arg0 point)))
        (s3-0 (-> this poly-hash bucket-size))
        (s2-0 0)
        )
    (until (zero? v1-15)
      (let ((s1-0 (* s2-0 8))
            (s0-0 (-> s4-0 0))
            )
        (b! (zero? s0-0) cfg-17 :delay (nop!))
        ;; og:preserve-this
        (label cfg-2)
        (let ((v1-2 (logand s0-0 1)))
          (nop!)
          (b! (zero? v1-2) cfg-16 :delay (nop!))
          )
        (set! sv-16 (-> this poly-array s1-0))
        (let ((v1-5 sv-16)
              (f0-0 (-> arg0 point y))
              (f1-0 (-> arg0 y-threshold))
              )
          (b! (>= (+ (-> v1-5 vertex3 w) f1-0) f0-0) cfg-5 :delay (set! a0-3 #t))
          (set! a0-3 #f)
          (label cfg-5)
          (set! v1-6 (and a0-3 (begin (b! (>= f0-0 (- (-> v1-5 vertex2 w) f1-0)) cfg-9 :delay (set! v1-6 #t)) #f)))
          )
        (label cfg-9)
        (when (and v1-6 (not (logtest? (-> sv-16 pat) (-> arg0 ignore))))
          (if (point-in-poly? this sv-16 (-> arg0 point))
              (return sv-16)
              )
          )
        (label cfg-16)
        ;; og:preserve-this
        (set! s0-0 (the-as uint (/ (the-as int s0-0) 2)))
        (nop!)
        (b! (nonzero? s0-0) cfg-2 :delay (set! s1-0 (+ s1-0 1)))
        )
      (label cfg-17)
      (+! s2-0 1)
      (set! s4-0 (&-> s4-0 1))
      (set-on-less-than v1-15 s2-0 s3-0)
      (nop!)
      )
    )
  0
  (the-as nav-poly #f)
  )

(defmethod is-in-mesh-local? ((this nav-mesh) (arg0 vector) (arg1 float) (arg2 float))
  (local-vars (v1-3 float) (sv-16 float) (sv-20 vector) (sv-24 float))
  (rlet ((acc :class vf)
         (vf0 :class vf)
         (vf1 :class vf)
         (vf2 :class vf)
         )
    (init-vf0-vector)
    (set! sv-16 arg2)
    (set! sv-20 arg0)
    (set! sv-24 arg1)
    (let* ((f0-3 (+ sv-24 (-> this bounds w)))
           (f0-5 (* f0-3 f0-3))
           )
      (.lvf vf1 (&-> sv-20 quad))
      (.add.w.vf.x vf2 vf0 vf0)
      (.mul.vf vf1 vf1 vf1)
      (.mul.x.vf.x acc vf2 vf1)
      (.add.mul.y.vf.x acc vf2 vf1 acc)
      (.add.mul.z.vf.x vf1 vf2 vf1 acc)
      (.mov v1-3 vf1)
      (when (>= f0-5 v1-3)
        (let ((s5-0 (new 'stack-no-clear 'nav-find-poly-parms)))
          (set! (-> s5-0 point quad) (-> sv-20 quad))
          (set! (-> s5-0 y-threshold) sv-16)
          (set! (-> s5-0 ignore) (the-as uint 2))
          (find-nearest-poly-to-point-local this s5-0)
          (cond
            ((-> s5-0 point-inside?)
             #t
             )
            (else
              (let ((s4-0 (new 'stack-no-clear 'vector)))
                (project-point-into-poly-2d this (-> s5-0 poly) s4-0 sv-20)
                (let ((f0-7 (vector-vector-xz-distance-squared s4-0 sv-20))
                      (f1-2 sv-24)
                      )
                  (< f0-7 (* f1-2 f1-2))
                  )
                )
              )
            )
          )
        )
      )
    )
  )

(defun init-ray-local ((arg0 nav-ray) (arg1 nav-poly) (arg2 vector) (arg3 vector))
  (rlet ((acc :class vf)
         (Q :class vf)
         (vf0 :class vf)
         (vf1 :class vf)
         (vf2 :class vf)
         (vf3 :class vf)
         )
    (init-vf0-vector)
    (set! (-> arg0 current-pos quad) (-> arg2 quad))
    (set! (-> arg0 dest-pos quad) (-> arg3 quad))
    (set! (-> arg0 current-poly) arg1)
    (let ((v1-2 arg0))
      (vector-! (-> v1-2 dir) (-> v1-2 dest-pos) (-> v1-2 current-pos))
      (set! (-> v1-2 dir y) 0.0)
      (let ((a0-2 (-> v1-2 dir)))
        (let ((f0-1 1.0))
          (.lvf vf1 (&-> a0-2 quad))
          (.mul.vf.xyz vf2 vf1 vf1)
          (let ((a1-3 f0-1))
            (.mov vf3 a1-3)
            )
          )
        (.mul.x.vf.w acc vf0 vf2)
        (.add.mul.y.vf.w acc vf0 vf2 acc)
        (.add.mul.z.vf.w vf2 vf0 vf2 acc)
        (.isqrt.vf Q vf3 vf2 :fsf #b0 :ftf #b11)
        (.wait.vf)
        (.mul.vf.xyz vf1 vf1 Q)
        (.nop.vf)
        (.nop.vf)
        (.nop.vf)
        (.svf (&-> a0-2 quad) vf1)
        )
      (set! (-> v1-2 next-poly) #f)
      (set! (-> v1-2 len) 0.0)
      (set! (-> v1-2 last-edge) -1)
      (set! (-> v1-2 terminated) #f)
      (set! (-> v1-2 reached-dest) #f)
      (set! (-> v1-2 hit-boundary) #f)
      (set! (-> v1-2 hit-gap) #f)
      (set! (-> v1-2 ignore) (the-as uint 3))
      )
    0
    (none)
    )
  )

(defun init-ray-dir-local ((arg0 nav-ray) (arg1 nav-poly) (arg2 vector) (arg3 vector) (arg4 float))
  (rlet ((acc :class vf)
         (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)
         )
    (init-vf0-vector)
    (set! (-> arg0 current-poly) arg1)
    (set! (-> arg0 current-pos quad) (-> arg2 quad))
    (let ((a1-3 (-> arg0 dest-pos)))
      (let ((v1-1 (-> arg0 current-pos)))
        (let ((a2-1 arg3))
          (let ((a3-1 arg4))
            (.mov vf7 a3-1)
            )
          (.lvf vf5 (&-> a2-1 quad))
          )
        (.lvf vf4 (&-> v1-1 quad))
        )
      (.add.x.vf.w vf6 vf0 vf0)
      (.mul.x.vf.xyz acc vf5 vf7)
      (.add.mul.w.vf.xyz vf6 vf4 vf0 acc)
      (.svf (&-> a1-3 quad) vf6)
      )
    (let ((v1-2 arg0))
      (vector-! (-> v1-2 dir) (-> v1-2 dest-pos) (-> v1-2 current-pos))
      (set! (-> v1-2 dir y) 0.0)
      (let ((a0-2 (-> v1-2 dir)))
        (let ((f0-2 1.0))
          (.lvf vf1 (&-> a0-2 quad))
          (.mul.vf.xyz vf2 vf1 vf1)
          (let ((a1-6 f0-2))
            (.mov vf3 a1-6)
            )
          )
        (.mul.x.vf.w acc vf0 vf2)
        (.add.mul.y.vf.w acc vf0 vf2 acc)
        (.add.mul.z.vf.w vf2 vf0 vf2 acc)
        (.isqrt.vf Q vf3 vf2 :fsf #b0 :ftf #b11)
        (.wait.vf)
        (.mul.vf.xyz vf1 vf1 Q)
        (.nop.vf)
        (.nop.vf)
        (.nop.vf)
        (.svf (&-> a0-2 quad) vf1)
        )
      (set! (-> v1-2 next-poly) #f)
      (set! (-> v1-2 len) 0.0)
      (set! (-> v1-2 last-edge) -1)
      (set! (-> v1-2 terminated) #f)
      (set! (-> v1-2 reached-dest) #f)
      (set! (-> v1-2 hit-boundary) #f)
      (set! (-> v1-2 hit-gap) #f)
      (set! (-> v1-2 ignore) (the-as uint 3))
      )
    0
    (none)
    )
  )

(defmethod try-move-along-ray ((this nav-mesh) (arg0 nav-poly) (arg1 vector) (arg2 vector) (arg3 float))
  (local-vars (v1-2 symbol))
  (let ((gp-0 (new 'stack-no-clear 'nav-ray)))
    (let ((s4-0 0))
      (init-ray-dir-local gp-0 arg0 arg1 arg2 arg3)
      (until v1-2
        (+! s4-0 1)
        (move-along-nav-ray! this gp-0)
        (set! v1-2 (or (>= s4-0 15) (-> gp-0 terminated)))
        )
      )
    (-> gp-0 len)
    )
  )

(defun nav-ray-test ((arg0 nav-mesh) (arg1 nav-poly) (arg2 vector) (arg3 vector))
  (let ((s4-1 (vector-! (new 'stack-no-clear 'vector) arg2 (-> arg0 bounds)))
        (s3-1 (vector-! (new 'stack-no-clear 'vector) arg3 arg2))
        )
    0.0
    (set! (-> s3-1 y) 0.0)
    (let ((f30-0 (vector-vector-xz-distance arg2 arg3)))
      (vector-xz-normalize! s3-1 1.0)
      (try-move-along-ray arg0 arg1 s4-1 s3-1 f30-0)
      )
    )
  )

(defun point-poly-distance-min ((arg0 nav-mesh-work) (arg1 nav-poly) (arg2 float) (arg3 nav-poly))
  (let ((t0-0 (-> arg3 vertex-count))
        (a3-1 (-> arg3 vertex))
        (f0-0 arg2)
        )
    (let ((v1-0 0))
      (let ((f1-0 (-> arg1 vertex0 x))
            (f2-0 (-> arg1 vertex0 z))
            (a1-1 0)
            )
        (b! #t cfg-10 :delay (nop!))
        (label cfg-1)
        (let* ((t2-0 (-> a3-1 (-> arg0 vert0-table a1-1)))
               (t1-6 (-> a3-1 (-> arg0 vert1-table a1-1)))
               (f5-0 (- (-> t1-6 x) (-> t2-0 x)))
               (f6-0 (- (-> t1-6 z) (-> t2-0 z)))
               (f4-2 (- f1-0 (-> t2-0 x)))
               (f3-4 (- f2-0 (-> t2-0 z)))
               (f7-1 (- (* f5-0 f3-4) (* f6-0 f4-2)))
               )
          (b! (>= 0.0 f7-1) cfg-9 :delay #f)
          (+! v1-0 1)
          (let* ((f8-2 f5-0)
                 (f8-4 (* f8-2 f8-2))
                 (f9-0 f6-0)
                 (f8-5 (+ f8-4 (* f9-0 f9-0)))
                 )
            (let* ((f9-3 arg2)
                   (f9-6 (* f8-5 (* f9-3 f9-3)))
                   (f10-0 f7-1)
                   )
              (b! (< f9-6 (* f10-0 f10-0)) cfg-13)
              )
            (let ((f5-2 (+ (* f5-0 f4-2) (* f6-0 f3-4))))
              arg2
              (b! (>= f5-2 0.0) cfg-5)
              (let ((f3-8 (sqrtf (+ (* f4-2 f4-2) (* f3-4 f3-4)))))
                (b! #t cfg-8 :delay (nop!))
                (label cfg-5)
                (b! (>= f8-5 f5-2) cfg-7)
                (let* ((f3-10 (- f1-0 (-> t1-6 x)))
                       (f3-12 (* f3-10 f3-10))
                       (f4-6 (- f2-0 (-> t1-6 z)))
                       )
                  (set! f3-8 (sqrtf (+ f3-12 (* f4-6 f4-6))))
                  )
                (b! #t cfg-8 :delay (nop!))
                (label cfg-7)
                (set! f0-0 (/ f7-1 (sqrtf f8-5)))
                (b! #t cfg-13 :delay (nop!))
                (label cfg-8)
                (set! f0-0 (fmin f0-0 f3-8))
                )
              )
            )
          )
        (label cfg-9)
        (+! a1-1 1)
        (label cfg-10)
        (b! (< a1-1 (the-as int t0-0)) cfg-1)
        )
      (b! (nonzero? v1-0) cfg-13 :delay (empty-form))
      )
    (set! f0-0 0.0)
    (label cfg-13)
    f0-0
    )
  )

(defmethod find-nearest-poly-to-point-local ((this nav-mesh) (arg0 nav-find-poly-parms))
  (local-vars
    (v1-16 int)
    (v1-34 int)
    (sv-16 nav-poly)
    (sv-20 (pointer uint8))
    (sv-24 nav-poly)
    (sv-28 float)
    (sv-32 int)
    (sv-40 int)
    (sv-48 nav-poly)
    (sv-52 float)
    )
  (set! sv-16 (the-as nav-poly #f))
  (set! sv-20 (search-for-sphere (-> this poly-hash) (-> arg0 point) 12288.0))
  (set! (-> arg0 point-inside?) #f)
  (let ((s4-0 (-> this poly-hash bucket-size))
        (s3-0 sv-20)
        (s2-0 0)
        )
    (nop!)
    (label cfg-1)
    (let ((s1-0 (* s2-0 8))
          (s0-0 (-> s3-0 0))
          )
      (b! (zero? s0-0) cfg-17 :delay (nop!))
      ;; og:preserve-this
      (label cfg-2)
      (let ((v1-3 (logand s0-0 1)))
        (nop!)
        (b! (zero? v1-3) cfg-16 :delay (nop!))
        )
      (set! sv-24 (-> this poly-array s1-0))
      (let ((v1-6 sv-24)
            (f0-0 (-> arg0 point y))
            (f1-0 (-> arg0 y-threshold))
            )
        (b!
          (not (and (and (>= (+ (-> v1-6 vertex3 w) f1-0) f0-0) (>= f0-0 (- (-> v1-6 vertex2 w) f1-0)))
                    (not (logtest? (-> sv-24 pat) (-> arg0 ignore)))
                    )
               )
          cfg-16
          :delay (empty-form)
          )
        )
      (b! (not (point-in-poly? this sv-24 (-> arg0 point))) cfg-16 :delay (empty-form))
      (set! (-> arg0 point-inside?) #t)
      (set! (-> arg0 dist) 0.0)
      (set! sv-16 sv-24)
      (b! #t cfg-38 :delay (nop!))
      (nop!)
      (label cfg-16)
      ;; og:preserve-this cast
      (set! s0-0 (the-as uint (/ (the-as int s0-0) 2)))
      (nop!)
      (b! (nonzero? s0-0) cfg-2 :delay (set! s1-0 (+ s1-0 1)))
      )
    (label cfg-17)
    (+! s2-0 1)
    (set! s3-0 (&-> s3-0 1))
    (set-on-less-than v1-16 s2-0 s4-0)
    )
  (nop!)
  (b! (nonzero? v1-16) cfg-1 :delay (nop!))
  (set! sv-28 (the-as float 10000000000000000000000000000000000000.0))
  (set! sv-32 0)
  (set! sv-40 0)
  (let ((s4-1 (-> this poly-hash bucket-size))
        (s3-1 sv-20)
        (s2-1 0)
        )
    (until (zero? v1-34)
      (let ((s1-1 (* s2-1 8))
            (s0-1 (-> s3-1 0))
            )
        (b! (zero? s0-1) cfg-34 :delay (nop!))
        ;; og:preserve-this
        (label cfg-20)
        (let ((v1-19 (logand s0-1 1)))
          (nop!)
          (b! (zero? v1-19) cfg-33 :delay (nop!))
          )
        (set! sv-48 (-> this poly-array s1-1))
        (let ((v1-22 sv-48)
              (f0-3 (-> arg0 point y))
              (f1-2 (-> arg0 y-threshold))
              )
          (when (and (and (>= (+ (-> v1-22 vertex3 w) f1-2) f0-3) (>= f0-3 (- (-> v1-22 vertex2 w) f1-2)))
                     (not (logtest? (-> sv-48 pat) (-> arg0 ignore)))
                     )
            (set! sv-40 (+ sv-40 1))
            (set! sv-52 (point-poly-distance-min (-> this work) (the-as nav-poly (-> arg0 point)) sv-28 sv-48))
            (when (< sv-52 sv-28)
              (set! sv-28 sv-52)
              (set! sv-16 sv-48)
              (nop!)
              )
            )
          )
        (label cfg-33)
        ;; og:preserve-this cast
        (set! s0-1 (the-as uint (/ (the-as int s0-1) 2)))
        (nop!)
        (b! (nonzero? s0-1) cfg-20 :delay (set! s1-1 (+ s1-1 1)))
        )
      (label cfg-34)
      (+! s2-1 1)
      (set! s3-1 (&-> s3-1 1))
      (set-on-less-than v1-34 s2-1 s4-1)
      (nop!)
      )
    )
  (if (not sv-16)
      (set! sv-16 (-> this poly-array 0))
      )
  (set! (-> arg0 dist) sv-28)
  (label cfg-38)
  (set! (-> arg0 poly) sv-16)
  arg0
  )

(defun nav-mesh-route-table-bit-index ((arg0 nav-mesh) (arg1 uint) (arg2 int))
  (* (+ arg2 (* arg1 (-> arg0 poly-count))) 2)
  )

(defmethod get-route-portal ((this nav-mesh) (arg0 nav-poly) (arg1 nav-poly) (arg2 nav-route-portal))
  (set! (-> arg2 next-poly) #f)
  (cond
    ((and arg0 arg1 (!= arg0 arg1))
     (let* ((a1-1 this)
            (v1-1 (-> arg0 id))
            (v1-4 (* (+ (-> arg1 id) (* v1-1 (-> a1-1 poly-count))) 2))
            (s3-0
              (logand (ash (-> (the-as (pointer uint8) (&+ (-> this route) (shr v1-4 3)))) (- (the-as int (logand v1-4 7))))
                      3
                      )
              )
            )
       (set! (-> arg2 edge-index) -1)
       (let ((s2-0 (-> arg0 adj-poly s3-0)))
         (when (= s2-0 255)
           (format 0 "nav-mesh::get-route-portal: data error in nav mesh~%")
           (break!)
           0
           )
         (set! (-> arg2 edge-index) (the-as int s3-0))
         (set! (-> arg2 next-poly) (-> this poly-array s2-0))
         )
       (let ((a0-7 s3-0)
             (v1-16 (the-as int (+ s3-0 1)))
             )
         (if (>= (the-as uint v1-16) (-> arg0 vertex-count))
             (set! v1-16 0)
             )
         (set! (-> arg2 vertex 1 quad) (-> arg0 vertex a0-7 quad))
         (let ((v0-1 (-> arg2 vertex)))
           (set! (-> v0-1 0 quad) (-> arg0 vertex v1-16 quad))
           v0-1
           )
         )
       )
     )
    (else
      (the-as (inline-array nav-vertex) #f)
      )
    )
  )

(defmethod lookup-poly-on-route-to-target ((this nav-mesh) (arg0 nav-poly) (arg1 nav-poly))
  (cond
    ((and arg0 arg1 (!= arg0 arg1))
     (let* ((a3-0 this)
            (v1-1 (-> arg0 id))
            (v1-4 (* (+ (-> arg1 id) (* v1-1 (-> a3-0 poly-count))) 2))
            (v1-9
              (logand (ash (-> (the-as (pointer uint8) (&+ (-> this route) (shr v1-4 3)))) (- (the-as int (logand v1-4 7))))
                      3
                      )
              )
            (a2-5 (new 'stack-no-clear 'array 'int8 4))
            )
       (set! (-> a2-5 0) (the-as int (-> arg0 adj-poly0)))
       (set! (-> a2-5 1) (the-as int (-> arg0 adj-poly1)))
       (set! (-> a2-5 2) (the-as int (-> arg0 adj-poly2)))
       (set! (-> a2-5 3) (the-as int (-> arg0 adj-poly3)))
       (let ((v1-11 (-> (the-as (pointer uint8) (&+ a2-5 v1-9)))))
         (if (= v1-11 255)
             (the-as nav-poly #f)
             (-> this poly-array v1-11)
             )
         )
       )
     )
    (else
      (the-as nav-poly #f)
      )
    )
  )

(defmethod compute-bounding-box-from-vertices ((this nav-mesh) (arg0 vector) (arg1 vector))
  (let ((f0-0 10000000000000000000000000000000000000.0)
        (f1-0 -10000000000000000000000000000000000000.0)
        )
    (set! (-> arg0 x) f0-0)
    (set! (-> arg0 y) f0-0)
    (set! (-> arg0 z) f0-0)
    (set! (-> arg1 x) f1-0)
    (set! (-> arg1 y) f1-0)
    (set! (-> arg1 z) f1-0)
    )
  (dotimes (v1-3 (the-as int (-> this poly-count)))
    (let ((a3-1 (-> this poly-array v1-3)))
      (dotimes (t0-1 (the-as int (-> a3-1 vertex-count)))
        (let ((t1-2 (-> a3-1 vertex t0-1)))
          (set! (-> arg0 x) (fmin (-> arg0 x) (-> t1-2 x)))
          (set! (-> arg0 y) (fmin (-> arg0 y) (-> t1-2 y)))
          (set! (-> arg0 z) (fmin (-> arg0 z) (-> t1-2 z)))
          (set! (-> arg1 x) (fmax (-> arg1 x) (-> t1-2 x)))
          (set! (-> arg1 y) (fmax (-> arg1 y) (-> t1-2 y)))
          (set! (-> arg1 z) (fmax (-> arg1 z) (-> t1-2 z)))
          )
        )
      )
    )
  (vector+! arg0 arg0 (-> this bounds))
  (vector+! arg1 arg1 (-> this bounds))
  0
  (none)
  )

(defmethod initialize-mesh! ((this nav-mesh))
  (local-vars
    (sv-32 vector)
    (sv-36 uint)
    (sv-40 int)
    (sv-48 int)
    (sv-56 int)
    (sv-64 symbol)
    (sv-68 (inline-array vector))
    (sv-72 vector)
    (sv-76 vector)
    )
  (with-pp
    (rlet ((acc :class vf)
           (Q :class vf)
           (vf0 :class vf)
           (vf1 :class vf)
           (vf2 :class vf)
           (vf3 :class vf)
           )
      (init-vf0-vector)
      (set! sv-32 (new 'stack-no-clear 'vector))
      (set! sv-36 (-> this poly-count))
      (set! sv-40 0)
      (set! sv-48 0)
      (set! sv-56 0)
      (set! sv-64 (the-as symbol #f))
      (countdown (s5-0 sv-36)
        (let ((v1-3 (-> this poly-array s5-0)))
          (if (logtest? (-> v1-3 pat) 1)
              (set! sv-56 (+ sv-56 1))
              )
          (set! sv-68 (-> v1-3 vertex))
          (set! sv-72 (-> v1-3 vertex1))
          (set! sv-76 (-> v1-3 vertex2))
          )
        (vector-3pt-cross! sv-32 (the-as vector sv-68) sv-72 sv-76)
        (cond
          ((= (vector-length sv-32) 0.0)
           (set! sv-40 (+ sv-40 1))
           )
          (else
            (let ((v1-9 sv-32))
              (let ((f0-1 1.0))
                (.lvf vf1 (&-> v1-9 quad))
                (.mul.vf.xyz vf2 vf1 vf1)
                (let ((a0-11 f0-1))
                  (.mov vf3 a0-11)
                  )
                )
              (.mul.x.vf.w acc vf0 vf2)
              (.add.mul.y.vf.w acc vf0 vf2 acc)
              (.add.mul.z.vf.w vf2 vf0 vf2 acc)
              (.isqrt.vf Q vf3 vf2 :fsf #b0 :ftf #b11)
              (.wait.vf)
              (.mul.vf.xyz vf1 vf1 Q)
              (.nop.vf)
              (.nop.vf)
              (.nop.vf)
              (.svf (&-> v1-9 quad) vf1)
              )
            (if (>= 0.0 (-> sv-32 y))
                (set! sv-48 (+ sv-48 1))
                )
            )
          )
        )
      (when (zero? sv-36)
        (format #t "WARNING:  nav-mesh has no triangles. ")
        (set! sv-64 #t)
        )
      (when (> sv-40 0)
        (format #t "WARNING:  nav-mesh has ~D triangles with zero area (out of ~D triangles). " sv-40 sv-36)
        (set! sv-64 #t)
        )
      (when (> sv-48 0)
        (format #t "WARNING:  nav-mesh has ~D triangles with inverted normals (out of ~D triangles). " sv-48 sv-36)
        (set! sv-64 #t)
        )
      (when (< (the-as uint 255) sv-36)
        (format #t "WARNING:  nav-mesh has ~D triangles (only up to ~D are allowed). " sv-36 255)
        (set! sv-64 #t)
        )
      (when (= sv-56 sv-36)
        (format #t "WARNING:  nav-mesh only contains gap triangles (~D triangles total). " sv-36)
        (set! sv-64 #t)
        )
      (when sv-64
        (if pp
            (format #t "current process is ~A~%" (-> pp name))
            (format #t "(no current process).~%")
            )
        )
      0
      (none)
      )
    )
  )

(defun ray-ccw-line-segment-intersection? ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 vector))
  (let ((f0-2 (- (* (-> arg2 x) (-> arg1 z)) (* (-> arg2 z) (-> arg1 x))))
        (f2-4 (- (* (-> arg3 x) (-> arg1 z)) (* (-> arg3 z) (-> arg1 x))))
        (f3-4 (- (* (-> arg0 x) (-> arg1 z)) (* (-> arg0 z) (-> arg1 x))))
        (v0-0 #f)
        )
    (let ((f1-7 (- f2-4 f0-2))
          (f2-5 (- f2-4 f3-4))
          (f3-5 (- f3-4 f0-2))
          )
      (when (and (>= (fabs f1-7) (fmax (fabs f3-5) (fabs f2-5))) (!= f1-7 0.0))
        (let ((f0-7 (+ (* (-> arg1 x) (- (-> arg3 z) (-> arg2 z))) (* (-> arg1 z) (- (-> arg2 x) (-> arg3 x))))))
          (set! v0-0 (< 0.0 f0-7))
          )
        )
      )
    v0-0
    )
  )

(defun ray-line-segment-intersection? ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 vector))
  (let ((f1-3 (- (* (-> arg2 x) (-> arg1 z)) (* (-> arg2 z) (-> arg1 x))))
        (f0-4 (- (* (-> arg3 x) (-> arg1 z)) (* (-> arg3 z) (-> arg1 x))))
        (f2-6 (- (* (-> arg0 x) (-> arg1 z)) (* (-> arg0 z) (-> arg1 x))))
        (gp-0 #f)
        )
    (let ((f30-0 (- f0-4 f1-3))
          (f0-5 (- f0-4 f2-6))
          (f1-4 (- f2-6 f1-3))
          )
      (when (and (>= (fabs f30-0) (fmax (fabs f1-4) (fabs f0-5))) (!= f30-0 0.0))
        (let ((f2-11 (+ (* (-> arg2 x) (-> arg1 x)) (* (-> arg2 z) (-> arg1 z))))
              (f3-11 (+ (* (-> arg3 x) (-> arg1 x)) (* (-> arg3 z) (-> arg1 z))))
              (f28-0 (+ (* (-> arg0 x) (-> arg1 x)) (* (-> arg0 z) (-> arg1 z))))
              )
          (if (>= (* (+ (* f2-11 f0-5) (* f3-11 f1-4)) (sign f30-0)) (* f28-0 (fabs f30-0)))
              (set! gp-0 #t)
              )
          )
        )
      )
    gp-0
    )
  )

(defmethod nav-mesh-method-38 ((this nav-mesh) (arg0 nav-poly) (arg1 vector) (arg2 vector) (arg3 vector) (arg4 (pointer nav-poly)))
  (local-vars
    (s1-0 vector)
    (sv-16 int)
    (sv-24 nav-mesh-work)
    (sv-28 uint)
    (sv-32 (pointer int8))
    (sv-36 (pointer int8))
    (sv-40 vector)
    (sv-44 vector)
    )
  (set! sv-16 -1)
  (set! sv-24 (-> this work))
  (set! sv-28 (-> arg0 vertex-count))
  (set! sv-32 (-> sv-24 vert0-table))
  (set! sv-36 (-> sv-24 vert1-table))
  (set! (-> arg2 quad) (-> arg3 quad))
  (dotimes (v1-8 (the-as int sv-28))
    (set! sv-40 (-> arg0 vertex (-> sv-32 v1-8)))
    (set! sv-44 (-> arg0 vertex (-> sv-36 v1-8)))
    (let* ((f0-1 (- (-> sv-40 z) (-> sv-44 z)))
           (f1-2 (- (-> sv-44 x) (-> sv-40 x)))
           (f2-4 (+ (* f0-1 (- (-> sv-40 x) (-> arg1 x))) (* f1-2 (- (-> sv-40 z) (-> arg1 z)))))
           (f0-3 (+ (* (-> arg2 x) f0-1) (* (-> arg2 z) f1-2)))
           )
      (when (< f2-4 f0-3)
        (set! sv-16 v1-8)
        (let ((f0-4 (/ f2-4 f0-3)))
          (set! (-> arg2 x) (* (-> arg2 x) f0-4))
          (set! (-> arg2 z) (* (-> arg2 z) f0-4))
          )
        )
      )
    )
  (when arg4
    (cond
      ((= sv-16 -1)
       (set! (-> arg4 0) #f)
       )
      (else
        (while (!= sv-16 -1)
          (let ((v1-16 (-> arg0 adj-poly sv-16)))
            (cond
              ((!= v1-16 255)
               (set! (-> arg4 0) (-> this poly-array v1-16))
               (set! sv-16 -1)
               )
              ((let ((a1-1 (-> arg0 vertex (-> sv-32 sv-16))))
                 (set! s1-0 (-> arg0 vertex (-> sv-36 sv-16)))
                 (< (vector-vector-xz-distance arg1 a1-1) (-> this work nav-poly-min-dist))
                 )
               (set! sv-16 (+ sv-16 -1))
               (if (< sv-16 0)
                   (set! sv-16 (the-as int (+ sv-28 -1)))
                   )
               )
              ((< (vector-vector-xz-distance arg1 s1-0) (-> this work nav-poly-min-dist))
               (set! sv-16 (+ sv-16 1))
               (when (>= sv-16 (the-as int sv-28))
                 (set! sv-16 0)
                 0
                 )
               )
              (else
                (set! (-> arg4 0) #f)
                (set! sv-16 -1)
                )
              )
            )
          )
        )
      )
    )
  (set! (-> arg2 y) (-> arg1 y))
  arg2
  )

(defun plane-height-at-xz-point ((arg0 plane) (arg1 vector))
  (/ (- (+ (* (-> arg1 x) (-> arg0 x)) (* (-> arg1 z) (-> arg0 z)) (-> arg0 w))) (-> arg0 y))
  )

(defun nav-normal-from-3-points ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 vector))
  (rlet ((acc :class vf)
         (Q :class vf)
         (vf0 :class vf)
         (vf1 :class vf)
         (vf2 :class vf)
         (vf3 :class vf)
         (vf4 :class vf)
         (vf5 :class vf)
         )
    (init-vf0-vector)
    (let ((v1-0 arg0))
      (let ((a0-1 arg1)
            (a2-1 arg3)
            )
        (.lvf vf3 (&-> arg2 quad))
        (.lvf vf1 (&-> a0-1 quad))
        (.lvf vf2 (&-> a2-1 quad))
        )
      (.sub.vf vf1 vf3 vf1)
      (.sub.vf vf2 vf3 vf2)
      (.outer.product.a.vf acc vf2 vf1)
      (.outer.product.b.vf vf4 vf1 vf2 acc)
      (.mul.vf vf5 vf4 vf4)
      (.add.y.vf.x vf5 vf5 vf5)
      (.add.z.vf.x vf5 vf5 vf5)
      (.isqrt.vf Q vf0 vf5 :fsf #b11 :ftf #b0)
      (.mov.vf.w vf4 vf0)
      (.wait.vf)
      (.mul.vf.xyz vf4 vf4 Q)
      (.nop.vf)
      (.nop.vf)
      (.svf (&-> v1-0 quad) vf4)
      )
    0
    (none)
    )
  )

(defmethod project-point-onto-plane-of-poly-local ((this nav-mesh) (arg0 nav-poly) (arg1 vector) (arg2 vector) (arg3 vector))
  (let ((s5-0 (new 'stack-no-clear 'vector)))
    (let ((s4-0 (new 'stack-no-clear 'vector)))
      (cond
        ((= (-> arg0 vertex-count) 3)
         (nav-normal-from-3-points s4-0 (the-as vector (-> arg0 vertex)) (-> arg0 vertex1) (-> arg0 vertex2))
         )
        ((let* ((v1-2 (-> arg0 vertex2))
                (a0-3 (-> arg0 vertex))
                (f0-1 (- (-> a0-3 0 x) (-> v1-2 x)))
                (f1-2 (- (-> a0-3 0 z) (-> v1-2 z)))
                (f2-2 (- (-> arg3 x) (-> v1-2 x)))
                (f0-3 (- (* f0-1 (- (-> arg3 z) (-> v1-2 z))) (* f1-2 f2-2)))
                )
           (< 0.0 f0-3)
           )
         (nav-normal-from-3-points s4-0 (the-as vector (-> arg0 vertex)) (-> arg0 vertex2) (-> arg0 vertex3))
         )
        (else
          (nav-normal-from-3-points s4-0 (the-as vector (-> arg0 vertex)) (-> arg0 vertex1) (-> arg0 vertex2))
          )
        )
      (set! (-> arg2 quad) (-> s4-0 quad))
      (set! (-> s4-0 w) (- (vector-dot s4-0 (the-as vector (-> arg0 vertex)))))
      (set! (-> s5-0 quad) (-> arg3 quad))
      (set! (-> s5-0 y) (/ (- (+ (* (-> arg3 x) (-> s4-0 x)) (* (-> arg3 z) (-> s4-0 z)) (-> s4-0 w))) (-> s4-0 y)))
      )
    (set! (-> arg1 quad) (-> s5-0 quad))
    )
  0
  (none)
  )

;; WARN: Return type mismatch int vs nav-mesh.
(defmethod mem-usage ((this nav-mesh) (arg0 memory-usage-block) (arg1 int))
  (set! (-> arg0 length) (max 46 (-> arg0 length)))
  (set! (-> arg0 data 45 name) "nav-mesh")
  (+! (-> arg0 data 45 count) 1)
  (let ((v1-6 (asize-of this)))
    (+! (-> arg0 data 45 used) v1-6)
    (+! (-> arg0 data 45 total) (logand -16 (+ v1-6 15)))
    )
  (set! (-> arg0 length) (max 46 (-> arg0 length)))
  (set! (-> arg0 data 45 name) "nav-mesh")
  (+! (-> arg0 data 45 count) 1)
  (let ((v1-16 (* (-> this poly-count) 64)))
    (+! (-> arg0 data 45 used) v1-16)
    (+! (-> arg0 data 45 total) (logand -16 (+ v1-16 15)))
    )
  (set! (-> arg0 length) (max 46 (-> arg0 length)))
  (set! (-> arg0 data 45 name) "nav-mesh")
  (+! (-> arg0 data 45 count) 1)
  (let* ((v1-25 (-> this poly-count))
         (v1-27 (shr (* v1-25 v1-25) 2))
         )
    (+! (-> arg0 data 45 used) v1-27)
    (+! (-> arg0 data 45 total) (logand -16 (+ v1-27 15)))
    )
  (the-as nav-mesh 0)
  )

(defun get-nav-mesh ((arg0 actor-id))
  (let ((gp-0 (the-as nav-mesh #f)))
    (let* ((s5-0 (entity-nav-mesh-by-aid arg0))
           (v1-0 (if (type? s5-0 entity-nav-mesh)
                     s5-0
                     )
                 )
           )
      (if v1-0
          (set! gp-0 (-> v1-0 nav-mesh))
          )
      )
    gp-0
    )
  )

(defun find-nearest-nav-mesh ((arg0 vector) (arg1 float))
  (local-vars (v1-15 float) (sv-64 nav-find-poly-parms) (sv-68 nav-mesh) (sv-72 float) (sv-76 vector))
  (rlet ((acc :class vf)
         (vf0 :class vf)
         (vf1 :class vf)
         (vf2 :class vf)
         )
    (init-vf0-vector)
    (set! sv-64 (new 'stack-no-clear 'nav-find-poly-parms))
    (set! sv-68 (the-as nav-mesh #f))
    (set! sv-72 arg1)
    (set! sv-76 arg0)
    (set! (-> sv-64 ignore) (the-as uint 7))
    (dotimes (gp-0 (-> *level* length))
      (let ((v1-5 (-> *level* level gp-0)))
        (when (= (-> v1-5 status) 'active)
          (let ((s5-0 (-> v1-5 bsp nav-meshes)))
            (when (nonzero? s5-0)
              (dotimes (s4-0 (-> s5-0 length))
                (let ((s3-0 (-> s5-0 s4-0 nav-mesh)))
                  (when s3-0
                    (vector-! (-> sv-64 point) sv-76 (-> s3-0 bounds))
                    (.lvf vf1 (&-> (-> sv-64 point) quad))
                    (.add.w.vf.x vf2 vf0 vf0)
                    (.mul.vf vf1 vf1 vf1)
                    (.mul.x.vf.x acc vf2 vf1)
                    (.add.mul.y.vf.x acc vf2 vf1 acc)
                    (.add.mul.z.vf.x vf1 vf2 vf1 acc)
                    (.mov v1-15 vf1)
                    (let ((f0-1 v1-15)
                          (f1-0 (-> s3-0 bounds w))
                          )
                      (when (< f0-1 (* f1-0 f1-0))
                        (set! (-> sv-64 y-threshold) (-> s3-0 nearest-y-threshold))
                        (find-nearest-poly-to-point-local s3-0 sv-64)
                        (when (>= sv-72 (-> sv-64 dist))
                          (set! sv-72 (-> sv-64 dist))
                          (set! sv-68 s3-0)
                          )
                        )
                      )
                    )
                  )
                )
              )
            )
          )
        )
      )
    sv-68
    )
  )

(defmethod nav-mesh-method-10 ((this nav-mesh) (arg0 vector) (arg1 vector) (arg2 nav-poly))
  (local-vars (sv-16 vector))
  (set! sv-16 arg0)
  (let ((gp-0 (new 'stack-no-clear 'nav-find-poly-parms)))
    (set! (-> gp-0 poly) arg2)
    (vector-! (-> gp-0 point) arg1 (-> this bounds))
    (when (or (not (-> gp-0 poly)) (not (point-in-poly? this (-> gp-0 poly) (-> gp-0 point))))
      (set! (-> gp-0 y-threshold) (-> this nearest-y-threshold))
      (set! (-> gp-0 ignore) (the-as uint 3))
      (find-nearest-poly-to-point-local this gp-0)
      (when (-> gp-0 poly)
        (project-point-into-poly-2d this (-> gp-0 poly) sv-16 (-> gp-0 point))
        (vector+! sv-16 sv-16 (-> this bounds))
        )
      )
    (-> gp-0 poly)
    )
  )

(defun point-to-poly-boundary ((arg0 nav-poly) (arg1 vector) (arg2 vector))
  (let ((gp-0 (new 'stack-no-clear 'inline-array 'vector 4)))
    (set! (-> gp-0 4 x) (the-as float #x7f800000))
    (let* ((s2-0 (-> arg0 vertex-count))
           (v1-1 (the-as int (+ s2-0 -1)))
           )
      (dotimes (s1-0 (the-as int s2-0))
        (when (= (-> arg0 adj-poly v1-1) 255)
          (set! (-> gp-0 2 quad) (-> arg0 vertex v1-1 quad))
          (set! (-> gp-0 3 quad) (-> arg0 vertex s1-0 quad))
          (set! (-> gp-0 2 y) (-> arg2 y))
          (set! (-> gp-0 3 y) (-> arg2 y))
          (set! (-> gp-0 2 w) 1.0)
          (set! (-> gp-0 3 w) 1.0)
          (let ((f0-5 (vector-segment-distance-point! arg2 (-> gp-0 2) (-> gp-0 3) (-> gp-0 0))))
            (when (< f0-5 (-> gp-0 4 x))
              (set! (-> gp-0 4 x) f0-5)
              (set! (-> gp-0 1 quad) (-> gp-0 0 quad))
              )
            )
          )
        (set! v1-1 s1-0)
        )
      )
    (set! (-> arg1 quad) (-> gp-0 1 quad))
    (-> gp-0 4 x)
    )
  )

(defmethod nav-mesh-method-34 ((this nav-mesh) (arg0 vector) (arg1 vector) (arg2 float))
  (local-vars (v1-8 symbol) (v1-13 int) (a1-2 symbol) (sv-80 vector) (sv-84 (pointer uint8)))
  (let ((gp-0 (new 'stack-no-clear 'nav-poly)))
    (set! sv-80 arg0)
    (set! (-> gp-0 vertex3 y) (the-as float #x7f800000))
    (set! (-> gp-0 vertex3 x) arg2)
    (set! (-> gp-0 vertex1 quad) (-> arg1 quad))
    (set! sv-84 (search-for-sphere (-> this poly-hash) (-> gp-0 vertex1) (-> gp-0 vertex3 x)))
    (let ((s4-0 (-> this poly-hash bucket-size))
          (s3-0 sv-84)
          (s2-0 0)
          )
      (until (zero? v1-13)
        (let ((s1-0 (* s2-0 8))
              (s0-0 (-> s3-0 0))
              )
          (b! (zero? s0-0) cfg-14 :delay (nop!))
          ;; og:preserve-this
          (label cfg-2)
          (let ((v1-5 (logand s0-0 1)))
            (nop!)
            (b! (zero? v1-5) cfg-13 :delay (nop!))
            )
          (let ((a0-5 (-> this poly-array s1-0)))
            (let ((v1-7 a0-5)
                  (f0-3 (-> gp-0 vertex1 y))
                  (f1-0 (-> this nearest-y-threshold))
                  )
              (b! (>= (+ (-> v1-7 vertex3 w) f1-0) f0-3) cfg-5 :delay (set! a1-2 #t))
              (set! a1-2 #f)
              (label cfg-5)
              (set! v1-8 (and a1-2 (begin (b! (>= f0-3 (- (-> v1-7 vertex2 w) f1-0)) cfg-9 :delay (set! v1-8 #t)) #f)))
              )
            (label cfg-9)
            (if v1-8
                (set! (-> gp-0 vertex3 z) (point-to-poly-boundary a0-5 (-> gp-0 vertex2) (-> gp-0 vertex1)))
                )
            )
          (when (< (-> gp-0 vertex3 z) (-> gp-0 vertex3 y))
            (set! (-> gp-0 vertex3 y) (-> gp-0 vertex3 z))
            (set! (-> gp-0 vertex 0 quad) (-> gp-0 vertex2 quad))
            (nop!)
            )
          (label cfg-13)
          ;; og:preserve-this cast
          (set! s0-0 (the-as uint (/ (the-as int s0-0) 2)))
          (nop!)
          (b! (nonzero? s0-0) cfg-2 :delay (set! s1-0 (+ s1-0 1)))
          )
        (label cfg-14)
        (+! s2-0 1)
        (set! s3-0 (&-> s3-0 1))
        (set-on-less-than v1-13 s2-0 s4-0)
        (nop!)
        )
      )
    0
    (set! (-> sv-80 quad) (-> gp-0 vertex 0 quad))
    (-> gp-0 vertex3 y)
    )
  )

;; WARN: new jak 2 until loop case, check carefully
(defmethod nav-mesh-method-35 ((this nav-mesh) (arg0 vector) (arg1 vector) (arg2 float))
  (let ((gp-0 (new 'stack-no-clear 'inline-array 'nav-poly 3)))
    (set! (-> gp-0 2 vertex3 y) arg2)
    (vector-! (the-as vector (-> gp-0 0)) arg0 (-> this bounds))
    (vector-! (-> gp-0 0 vertex1) arg1 (-> this bounds))
    (set! (-> gp-0 2 vertex1 quad) (-> gp-0 0 vertex0 quad))
    (set! (-> gp-0 2 vertex2 x) (-> this nearest-y-threshold))
    (set! (-> gp-0 2 data 36) (the-as uint 3))
    (let ((a1-4 (find-poly-containing-point-local this (the-as nav-find-poly-parms (-> gp-0 2 vertex1)))))
      (cond
        (a1-4
          (init-ray-local (the-as nav-ray (-> gp-0 1)) a1-4 (the-as vector (-> gp-0 0)) (-> gp-0 0 vertex1))
          (until #f
            (set! (-> gp-0 2 vertex3 z)
                  (nav-mesh-method-34 this (-> gp-0 0 vertex3) (the-as vector (-> gp-0 1)) (-> gp-0 2 vertex3 y))
                  )
            (b! (>= (-> gp-0 2 vertex3 z) (-> gp-0 2 vertex3 y)) cfg-4 :delay #f)
            (set! (-> gp-0 2 vertex3 y) (-> gp-0 2 vertex3 z))
            (set! (-> gp-0 0 vertex2 quad) (-> gp-0 0 vertex3 quad))
            (label cfg-4)
            (b! (-> gp-0 2 vertex0 x) cfg-6 :delay (nop!))
            (move-along-nav-ray! this (the-as nav-ray (-> gp-0 1)))
            )
          #f
          (label cfg-6)
          (if (-> gp-0 2 vertex0 z)
              (set! (-> gp-0 2 vertex3 y) (the-as float #xff800000))
              )
          )
        (else
          (set! (-> gp-0 2 vertex3 y) (the-as float #xff800000))
          )
        )
      )
    (-> gp-0 2 vertex3 y)
    )
  )

(none)

)
