jak-project/goal_src/jak2/engine/collide/collide-shape-h.gc
water111 6b6a565d1a
[jak2] more nav-related nan fixes (#2472)
Fixes citizens that disappear (permanently) when being pushed into a
"wall" which is the border of a nav mesh that is exactly aligned with
coordinate axes.
2023-04-12 19:43:31 -04:00

691 lines
26 KiB
Common Lisp

;;-*-Lisp-*-
(in-package goal)
;; name: collide-shape-h.gc
;; name in dgo: collide-shape-h
;; dgos: ENGINE, GAME
(declare-type collide-shape trsqv)
(declare-type collide-shape-moving collide-shape)
(declare-type control-info collide-shape-moving)
(declare-type touching-list structure)
(declare-type collide-query structure)
(declare-type water-info structure)
(declare-type collide-shape-prim-group basic)
(declare-type collide-cache-prim structure)
(declare-type collide-shape-prim basic)
(declare-type collide-cache basic)
(declare-type rigid-body structure)
(defenum collide-spec
:bitfield #t
:type uint32
(backgnd 0) ;; 1
(jak 1) ;; 2
(bot 2) ;; 4
(crate 3) ;; 8
(civilian 4) ;; 16
(enemy 5) ;; 32
(obstacle 6) ;; 64
(vehicle-sphere 7) ;; 128
(hit-by-player-list 8) ;; 256
(hit-by-others-list 9) ;; 512
(player-list 10) ;; 1024
(water 11) ;; 2048
(collectable 12) ;; 4096
(blocking-plane 13) ;; 8192
(projectile 14) ;; 16384
(jak-vulnerable 15) ;; 32768
(camera-blocker 16) ;; hi 1
(notice-blue-eco-powerup 17) ;; hi 2
(tobot 18) ;; hi 4
(pusher 19) ;; hi 8
(vehicle-mesh 20) ;; hi 16
(bot-targetable 21) ;; hi 32
(jak-vehicle 22) ;; hi 64
(special-obstacle 23) ;; hi 128
(mech-punch 24) ;; hi 256
(obstacle-for-jak 25) ;; hi 512
(vehicle-mesh-probeable 26) ;; hi 1024
(unknown-27 27)
(unknown-28 28)
(unknown-29 29)
(unknown-30 30)
(unknown-31 31)
(unknown-32 32)
(unknown-33 33)
(unknown-34 34)
(unknown-35 35)
(unknown-36 36)
(unknown-37 37)
(unknown-38 38)
(unknown-39 39)
(unknown-40 40)
(unknown-41 41)
(unknown-42 42)
(unknown-43 43)
(unknown-44 44)
(unknown-45 45)
(unknown-46 46)
(unknown-47 47)
(unknown-48 48)
(unknown-49 49)
(unknown-50 50)
(unknown-51 51)
(unknown-52 52)
(unknown-53 53)
(unknown-54 54)
(unknown-55 55)
(unknown-56 56)
(unknown-57 57)
(unknown-58 58)
(unknown-59 59)
(unknown-60 60)
(unknown-61 61)
(unknown-62 62)
(unknown-63 63)
)
(defenum collide-action
:bitfield #t
:type uint32
(solid 0) ;; 1
(semi-solid 1) ;; 2
(rideable 2) ;; 4
(can-ride 3) ;; 8
(dont-push-away 4) ;; 16
(pull-rider-can-collide 5) ;; 32
(deadly 6) ;; 64
(persistent-attack 7) ;; 128
(no-smack 8) ;; 256
(no-standon 9) ;; 512
(block-turn-around 10) ;; 1024
(check-edge 11) ;; 2048
(check-stuck 12) ;; 4096
(stuck-wall-escape 13) ;; 8192
(no-normal-reset 14) ;; 163884
(edge-grabbed 15) ;; 32768
(nav-sphere 16) ;; hi 1
)
(defenum overlaps-others-options
:type uint32
:bitfield #t
(oo0)
(oo1)
(oo2)
(oo3)
(oo4)
)
(defenum prim-type
:type int8
(prim -2)
(sphere -1)
(group 0)
(mesh 1)
(fake-prim 2)
)
(defenum cshape-moving-flags
:bitfield #t
:type uint64
(on-surface 0)
(on-ground 1)
(t-surface 2)
(t-wall 3)
(t-ceil 4)
(t-act 5)
(csmf06)
(csmf07)
(csmf08)
(csmf09)
(on-water 10)
(csmf11)
(csmf12)
(csmf13)
(csmf14)
(csmf15)
(csmf16)
(csmf17)
(csmf18)
(csmf19)
(csmf20)
(csmf21)
(csmf22)
(csmf23)
(csmf24)
(csmf25)
(csmf26)
(csmf27)
(csmf28)
(csmf29)
)
(defenum cshape-reaction-flags
:bitfield #t
:type uint32
(csrf00)
(csrf01)
(csrf02)
(csrf03)
(csrf04)
(csrf05)
(csrf06)
(csrf07)
(csrf08)
(csrf09)
(csrf10)
(csrf11)
(csrf12)
(csrf13)
(csrf14)
(csrf15)
(csrf16)
(csrf17)
(csrf18)
(csrf19)
(csrf20)
(csrf21)
(csrf22)
(csrf23)
(csrf24)
(csrf25)
(csrf26)
(csrf27)
(csrf28)
(csrf29)
(csrf30)
(csrf31)
)
(defenum collide-list-enum
(hit-by-player)
(usually-hit-by-player)
(hit-by-others)
(player)
)
(defenum collide-status
:bitfield #t
:type uint64
(on-surface 0)
(on-ground 1)
(touch-surface 2)
(touch-wall 3)
(touch-ceiling 4)
(touch-actor 5)
(on-special-surface 6)
(touch-edge 7)
(no-touch 8)
(blocked 9)
(on-water 10)
(impact-surface 11)
(touch-background 12)
(stuck 13)
(touch-ceiling-sticky 14)
(glance 15)
(probe-hit 16)
)
;; +++nav-flags
(defenum nav-flags
:type uint8
:bitfield #t
(has-root-sphere 0)
(has-extra-sphere 1)
(has-child-spheres 2)
)
;; ---nav-flags
(define-extern cshape-reaction-update-state (function control-info collide-query vector none))
(define-extern cshape-reaction-default (function control-info collide-query vector vector collide-status))
(define-extern cshape-reaction-just-move (function control-info collide-query vector collide-status))
;; DECOMP BEGINS
(deftype collide-rider (structure)
((rider-handle handle :offset-assert 0)
(sticky-prim collide-shape-prim :offset-assert 8)
(prim-ry float :offset-assert 12)
(rider-local-pos vector :inline :offset-assert 16)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
(deftype collide-rider-pool (basic)
((alloc-count int32 :offset-assert 4)
(riders collide-rider 20 :inline :offset-assert 16)
)
:method-count-assert 11
:size-assert #x290
:flag-assert #xb00000290
(:methods
(add-rider (_type_ handle) collide-rider 9)
(prepare (_type_) none 10)
)
)
(defmethod prepare collide-rider-pool ((obj collide-rider-pool))
"Gets this pool ready to be used to allow allocations. This should be called once at the start of every frame."
(set! (-> obj alloc-count) 0)
0
(none)
)
(deftype pull-rider-info (structure)
((rider collide-rider :offset-assert 0)
(rider-cshape collide-shape-moving :offset-assert 4)
(rider-delta-ry float :offset-assert 8)
(rider-dest vector :inline :offset-assert 16)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
(kmemopen global "collide-lists")
(define *collide-hit-by-player-list* (new 'global 'engine 'collide-hit-by-player-list (* 640 PROCESS_HEAP_MULT) connection))
(define *collide-hit-by-others-list* (new 'global 'engine 'collide-hit-by-others-list PROCESS_HEAP_MAX connection))
(define *collide-player-list* (new 'global 'engine 'collide-player-list 32 connection))
(kmemclose)
(deftype overlaps-others-params (structure)
((options overlaps-others-options :offset-assert 0)
(collide-with-filter collide-spec :offset-assert 4)
(tlist touching-list :offset-assert 8)
(filtered-root-collide-with collide-spec :offset-assert 12)
(filtered-child-collide-with collide-spec :offset-assert 16)
(filtered-other-collide-as collide-spec :offset-assert 20)
)
:method-count-assert 9
:size-assert #x18
:flag-assert #x900000018
)
(deftype move-above-ground-params (structure)
((gnd-collide-with collide-spec :offset-assert 0)
(popup float :offset-assert 4)
(dont-move-if-overlaps? symbol :offset-assert 8)
(hover-if-no-ground? symbol :offset-assert 12)
(overlaps-params overlaps-others-params :inline :offset-assert 16)
(new-pos vector :inline :offset-assert 48)
(old-gspot-pos vector :inline :offset-assert 64)
(old-gspot-normal vector :inline :offset-assert 80)
(pat pat-surface :offset-assert 96)
(on-ground? symbol :offset-assert 100)
(do-move? symbol :offset-assert 104)
)
:method-count-assert 9
:size-assert #x6c
:flag-assert #x90000006c
)
(deftype collide-prim-core (structure)
((world-sphere vector :inline :offset-assert 0)
(collide-as collide-spec :offset 16)
(collide-with collide-spec :offset-assert 20)
(action collide-action :offset-assert 24)
(prim-type prim-type :offset-assert 28)
(unused1 uint8 3 :offset-assert 29)
(quad uint128 2 :offset 0)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
(deftype collide-shape-prim (basic)
((cshape collide-shape :offset-assert 4)
(prim-id uint32 :offset-assert 8)
(transform-index int8 :offset-assert 12)
(unused2 int8 3 :offset-assert 13)
(prim-core collide-prim-core :inline :offset-assert 16)
(local-sphere vector :inline :offset-assert 48)
(world-sphere vector :inline :offset 16)
(collide-as collide-spec :offset 32)
(collide-with collide-spec :offset 36)
(action collide-action :offset 40)
(prim-type int8 :offset 44)
(radius float :offset 60)
(specific uint8 16 :offset-assert 64)
)
:method-count-assert 20
:size-assert #x50
:flag-assert #x1400000050
(:methods
(new (symbol type collide-shape uint int) _type_ 0)
(debug-draw (_type_) none 9)
(add-fg-prim-using-box (_type_ collide-cache) none 10)
(add-fg-prim-using-line-sphere (_type_ collide-cache object) none 11)
(overlaps-others-test (_type_ overlaps-others-params collide-shape-prim) symbol 12)
(overlaps-others-group (_type_ overlaps-others-params collide-shape-prim-group) symbol 13)
(collide-shape-prim-method-14 () none 14)
(collide-with-collide-cache-prim-mesh (_type_ collide-query collide-cache-prim) none 15)
(collide-with-collide-cache-prim-sphere (_type_ collide-query collide-cache-prim) none 16)
(on-platform-test (_type_ collide-shape-prim collide-query float) none 17)
(should-push-away-test (_type_ collide-shape-prim collide-query) none 18)
(should-push-away-a-group-test (_type_ collide-shape-prim-group collide-query) none 19)
)
)
(deftype collide-shape-prim-sphere (collide-shape-prim)
((pat pat-surface :offset 64)
(nav-radius float :offset 68)
)
:method-count-assert 20
:size-assert #x50
:flag-assert #x1400000050
(:methods
(new (symbol type collide-shape uint) _type_ 0)
)
)
(deftype collide-shape-prim-mesh (collide-shape-prim)
((mesh collide-mesh :offset 64)
(mesh-id int32 :offset 68)
(mesh-cache-id uint32 :offset 72)
(mesh-cache-entry collide-mesh-cache-entry :offset 76)
)
:method-count-assert 20
:size-assert #x50
:flag-assert #x1400000050
(:methods
(new (symbol type collide-shape uint uint) _type_ 0)
)
)
(deftype collide-shape-prim-group (collide-shape-prim)
((num-children uint8 :offset 64)
(num-alloc-children uint8 :offset 65)
(child (inline-array collide-shape-prim) :offset 68)
)
:method-count-assert 20
:size-assert #x50
:flag-assert #x1400000050
(:methods
(new (symbol type collide-shape uint int) _type_ 0)
)
)
(deftype collide-shape (trsqv)
((actor-hash-index int16 :offset 12)
(process process-drawable :offset-assert 140)
(max-iteration-count uint8 :offset-assert 144)
(nav-flags nav-flags :offset-assert 145)
(total-prims uint8 :offset-assert 146)
(num-riders uint8 :offset-assert 147)
(pat-ignore-mask pat-surface :offset-assert 148)
(event-self symbol :offset-assert 152)
(event-other symbol :offset-assert 156)
(root-prim collide-shape-prim :offset-assert 160)
(riders (inline-array collide-rider) :offset-assert 164)
(penetrate-using penetrate :offset-assert 168)
(penetrated-by penetrate :offset-assert 176)
(backup-collide-as collide-spec :offset-assert 184)
(backup-collide-with collide-spec :offset-assert 188)
(event-priority uint8 :offset-assert 192)
(rider-max-momentum float :offset-assert 196)
)
:method-count-assert 55
:size-assert #xc8
:flag-assert #x37000000c8
(:methods
(new (symbol type process-drawable collide-list-enum) _type_ 0)
(move-by-vector! (_type_ vector) none 28)
(move-to-point! (_type_ vector) none 29)
(debug-draw (_type_) none 30)
(fill-cache-for-shape (_type_ float collide-query) none 31)
(fill-cache-integrate-and-collide (_type_ vector collide-query meters) none 32)
(find-prim-by-id (_type_ uint) collide-shape-prim 33)
(find-prim-by-id-logtest (_type_ uint) collide-shape-prim 34)
(detect-riders! (_type_) symbol 35)
(build-bounding-box-for-shape (_type_ bounding-box float collide-spec) symbol 36)
(integrate-and-collide! (_type_ vector) none 37)
(find-collision-meshes (_type_) none 38)
(on-platform (_type_ collide-shape collide-query) symbol 39)
(find-overlapping-shapes (_type_ overlaps-others-params) symbol 40)
(shove-to-closest-point-on-path (_type_ attack-info float) vector 41)
(should-push-away (_type_ collide-shape collide-query) symbol 42)
(pull-rider! (_type_ pull-rider-info) none 43)
(pull-riders! (_type_) symbol 44)
(do-push-aways (_type_) collide-spec 45)
(update-transforms (_type_) none 46)
(set-collide-with! (_type_ collide-spec) none 47)
(set-collide-as! (_type_ collide-spec) none 48)
(modify-collide-as! (_type_ int collide-spec collide-spec) none 49)
(send-shoves (_type_ process touching-shapes-entry float float float) symbol 50)
(above-ground? (_type_ collide-query vector collide-spec float float float) symbol 51)
(water-info-init! (_type_ water-info collide-action) water-info 52)
(iterate-prims (_type_ (function collide-shape-prim none)) none 53)
(pusher-init (_type_) none 54)
)
)
(deftype collide-shape-moving (collide-shape)
((rider-time time-frame :offset-assert 200)
(rider-last-move vector :inline :offset-assert 208)
(trans-old vector :inline :offset-assert 224)
(trans-old-old vector :inline :offset 240)
(trans-old-old-old vector :inline :offset 256)
(poly-pat pat-surface :offset 272)
(cur-pat pat-surface :offset-assert 276)
(ground-pat pat-surface :offset-assert 280)
(status collide-status :offset-assert 288)
(old-status collide-status :offset-assert 296)
(prev-status collide-status :offset-assert 304)
(reaction-flag cshape-reaction-flags :offset-assert 312)
(reaction (function control-info collide-query vector vector collide-status) :offset-assert 316)
(no-reaction (function collide-shape-moving collide-query vector vector object) :offset-assert 320)
(local-normal vector :inline :offset-assert 336)
(surface-normal vector :inline :offset-assert 352)
(poly-normal vector :inline :offset-assert 368)
(ground-poly-normal vector :inline :offset-assert 384)
(gspot-pos vector :inline :offset-assert 400)
(gspot-normal vector :inline :offset-assert 416)
(grount-touch-point vector :inline :offset-assert 432)
(ground-impact-vel meters :offset-assert 448)
(surface-angle float :offset-assert 452)
(poly-angle float :offset-assert 456)
(touch-angle float :offset-assert 460)
(coverage float :offset-assert 464)
(dynam dynamics :offset-assert 468)
(surf surface :offset-assert 472)
)
:method-count-assert 68
:size-assert #x1dc
:flag-assert #x44000001dc
(:methods
(new (symbol type process-drawable collide-list-enum) _type_ 0)
(find-ground (_type_ collide-query collide-spec float float float) symbol 55)
(react-to-pat! (_type_ pat-surface) int 56)
(integrate-no-collide! (_type_ vector) none 57)
(integrate-for-enemy-no-mtg (_type_ vector overlaps-others-params) symbol 58)
(move-above-ground (_type_ vector move-above-ground-params) none 59)
(move-to-ground (_type_ float float symbol collide-spec) none 60)
(move-to-ground-point (_type_ vector vector vector) none 61)
(compute-acc-due-to-gravity (_type_ vector float) vector 62)
(collide-shape-moving-method-63 (_type_ rigid-body float) none 63)
(try-snap-to-surface (_type_ vector float float float) symbol 64)
(fill-and-try-snap-to-surface (_type_ vector float float float collide-query) symbol 65)
(step-collison! (_type_ vector vector float int) float 66)
(collide-with-all-collide-cache-prims (_type_ matrix collide-query) none 67)
)
)
(defmethod new collide-shape-prim ((allocation symbol) (type-to-make type) (arg0 collide-shape) (arg1 uint) (arg2 int))
(let ((v0-0 (object-new allocation type-to-make arg2)))
(set! (-> v0-0 cshape) arg0)
(set! (-> v0-0 prim-id) arg1)
(set! (-> v0-0 prim-core action) (collide-action))
(set! (-> v0-0 prim-core collide-as) (collide-spec))
(set! (-> v0-0 prim-core collide-with) (collide-spec))
(set! (-> v0-0 transform-index) -2)
(set! (-> v0-0 prim-core prim-type) (prim-type prim))
v0-0
)
)
;; WARN: Return type mismatch collide-shape-prim vs collide-shape-prim-sphere.
(defmethod new collide-shape-prim-sphere ((allocation symbol) (type-to-make type) (arg0 collide-shape) (arg1 uint))
(let ((v0-0 ((method-of-type collide-shape-prim new) allocation type-to-make arg0 arg1 80)))
(set! (-> (the-as collide-shape-prim-sphere v0-0) pat)
(new 'static 'pat-surface :mode (pat-mode obstacle) :material (pat-material stone))
)
(set! (-> (the-as collide-shape-prim-sphere v0-0) prim-core prim-type) (prim-type sphere))
(the-as collide-shape-prim-sphere v0-0)
)
)
;; WARN: Return type mismatch collide-shape-prim vs collide-shape-prim-mesh.
(defmethod new collide-shape-prim-mesh ((allocation symbol) (type-to-make type) (arg0 collide-shape) (arg1 uint) (arg2 uint))
(let ((v0-0 ((method-of-type collide-shape-prim new) allocation type-to-make arg0 arg2 80)))
(set! (-> (the-as collide-shape-prim-mesh v0-0) mesh) #f)
(set! (-> (the-as collide-shape-prim-mesh v0-0) mesh-id) (the-as int arg1))
(set! (-> (the-as collide-shape-prim-mesh v0-0) mesh-cache-id) (the-as uint 0))
(set! (-> (the-as collide-shape-prim-mesh v0-0) prim-core prim-type) (prim-type mesh))
(the-as collide-shape-prim-mesh v0-0)
)
)
;; WARN: Return type mismatch collide-shape-prim vs collide-shape-prim-group.
(defmethod new collide-shape-prim-group ((allocation symbol) (type-to-make type) (arg0 collide-shape) (arg1 uint) (arg2 int))
(let ((v0-0 ((method-of-type collide-shape-prim new) allocation type-to-make arg0 (the-as uint arg2) 80)))
(set! (-> (the-as collide-shape-prim-group v0-0) num-children) arg1)
(set! (-> (the-as collide-shape-prim-group v0-0) num-alloc-children) arg1)
(set! (-> (the-as collide-shape-prim-group v0-0) prim-core prim-type) (prim-type group))
(set! (-> (the-as collide-shape-prim-group v0-0) child)
(the-as (inline-array collide-shape-prim) (&+ (the-as collide-shape-prim-group v0-0) 80))
)
(the-as collide-shape-prim-group v0-0)
)
)
;; WARN: Return type mismatch uint vs int.
(defmethod length collide-shape-prim-group ((obj collide-shape-prim-group))
(the-as int (-> obj num-children))
)
(defmethod new collide-shape ((allocation symbol) (type-to-make type) (arg0 process-drawable) (arg1 collide-list-enum))
(let ((s5-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
(set! (-> s5-0 actor-hash-index) -1)
(set! (-> s5-0 process) arg0)
(set! (-> s5-0 max-iteration-count) (the-as uint 1))
(set! (-> s5-0 nav-flags) (nav-flags has-root-sphere))
(set! (-> s5-0 event-self) #f)
(set! (-> s5-0 event-other) #f)
(set! (-> s5-0 riders) (the-as (inline-array collide-rider) #f))
(set! (-> s5-0 root-prim) #f)
(set! (-> s5-0 penetrate-using) (penetrate))
(set! (-> s5-0 penetrated-by) (penetrate))
(set! (-> s5-0 event-priority) (the-as uint 0))
(set! (-> s5-0 rider-max-momentum) 409600.0)
(case (-> arg0 type symbol)
(('camera)
(set! (-> s5-0 pat-ignore-mask) (new 'static 'pat-surface :nocamera #x1 :probe #x1 :noendlessfall #x1))
)
(('target)
(set! (-> s5-0 pat-ignore-mask) (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1))
)
(else
(set! (-> s5-0 pat-ignore-mask)
(new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1)
)
)
)
(set! (-> s5-0 trans w) 1.0)
(quaternion-identity! (-> s5-0 quat))
(vector-identity! (-> s5-0 scale))
(cond
((= arg1 (collide-list-enum hit-by-player))
(add-connection *collide-hit-by-player-list* arg0 #f s5-0 #f #f)
)
((= arg1 (collide-list-enum usually-hit-by-player))
(add-connection *collide-hit-by-others-list* arg0 #f s5-0 #f #f)
)
((= arg1 (collide-list-enum hit-by-others))
(add-connection *collide-player-list* arg0 #f s5-0 #f #f)
)
(else
(format 0 "Unsupported collide-list-enum in collide-shape constructor!~%")
)
)
s5-0
)
)
;; WARN: Return type mismatch collide-shape vs collide-shape-moving.
(defmethod new collide-shape-moving ((allocation symbol) (type-to-make type) (arg0 process-drawable) (arg1 collide-list-enum))
(let ((v0-0 ((method-of-type collide-shape new) allocation type-to-make arg0 arg1)))
(set! (-> (the-as collide-shape-moving v0-0) gspot-pos y) -40959590.0)
(set! (-> (the-as collide-shape-moving v0-0) gspot-normal quad) (-> *y-vector* quad))
(set! (-> (the-as collide-shape-moving v0-0) surf) *standard-ground-surface*)
(the-as collide-shape-moving v0-0)
)
)
(define *collide-shape-prim-backgnd* (new 'static 'collide-shape-prim-mesh
:cshape #f
:prim-core (new 'static 'collide-prim-core
:world-sphere (new 'static 'vector :w 204800000.0)
:collide-as (collide-spec backgnd)
:action (collide-action solid)
:prim-type (prim-type fake-prim)
)
:local-sphere (new 'static 'vector :w 204800000.0)
:mesh #f
)
)
(define *collide-shape-prim-water* (new 'static 'collide-shape-prim-mesh
:cshape #f
:prim-core (new 'static 'collide-prim-core
:world-sphere (new 'static 'vector :w 204800000.0)
:collide-as (collide-spec water)
:action (collide-action solid)
:prim-type (prim-type fake-prim)
)
:local-sphere (new 'static 'vector :w 204800000.0)
:mesh #f
)
)
(define-perm *collide-rider-pool* collide-rider-pool (new 'global 'collide-rider-pool))
(defmacro normalized-heading-to-quaternion! (quat heading)
"Modified for PC. This does a clever trick, but it doesn't work if the heading is exactly
[0, 0, -1] because this tries to normalize a quaternion that's all 0's.
I think that, on ps2, something prevents the heading from being exactly 0, 0, -1,
but this doesn't happen on PC. A similar thing happened with Jak 1's punch glitch,
where some trig functions were slightly off from returning exactly 0.0 and 1.0 on ps2
rounding only."
`(begin
(if (and (= (-> ,heading x) 0.0)
(= (+ 1.0 (-> ,heading z)) 0.0)
)
(quaternion-set! ,quat 0.0 1.0 0.0 0.0)
(quaternion-set! ,quat 0.0 (-> ,heading x) 0.0 (+ 1.0 (-> ,heading z)))
)
(quaternion-normalize! ,quat)
)
)