mirror of
https://github.com/open-goal/jak-project
synced 2026-08-10 19:17:55 -04:00
clean up to entity-h
This commit is contained in:
@@ -63,7 +63,8 @@ FormElement* SetVarOp::get_as_form(FormPool& pool, const Env& env) const {
|
||||
pool.alloc_single_element_form<GenericElement>(
|
||||
nullptr, GenericOperator::make_fixed(FixedOperatorKind::ADDRESS_OF),
|
||||
pool.alloc_single_element_form<StackSpillValueElement>(
|
||||
nullptr, -1, offset, make_stack_slot_access(offset), false)),
|
||||
nullptr, -1, offset, env.get_stack_slot_access_for_op(m_my_idx, offset),
|
||||
false)),
|
||||
true, env.stack_slot_entries.at(offset).typespec);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -685,6 +685,21 @@ RegisterAccess Env::get_stack_slot_access_for_op(int op_id, int offset) const {
|
||||
return make_stack_slot_access(offset, it->second);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
std::optional<int> stack_slot_address_offset(const AtomicOp* op) {
|
||||
const auto* set = dynamic_cast<const SetVarOp*>(op);
|
||||
if (!set || set->src().kind() != SimpleExpression::Kind::ADD || set->src().args() != 2 ||
|
||||
!set->src().get_arg(0).is_var() ||
|
||||
set->src().get_arg(0).var().reg() != Register(Reg::GPR, Reg::SP) ||
|
||||
!set->src().get_arg(1).is_int()) {
|
||||
return {};
|
||||
}
|
||||
return set->src().get_arg(1).get_int();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Env::disable_def(const RegisterAccess& access, DecompWarnings& warnings) {
|
||||
if (is_stack_slot_access(access)) {
|
||||
// Stack-slot use/def info is intentionally immutable during expression building.
|
||||
@@ -732,6 +747,9 @@ void Env::rebuild_stack_slot_use_def_info() {
|
||||
offsets.insert(store->offset());
|
||||
} else if (auto* load = dynamic_cast<const StackSpillLoadOp*>(ops.ops.at(op_id).get())) {
|
||||
offsets.insert(load->offset());
|
||||
} else if (auto address_offset = stack_slot_address_offset(ops.ops.at(op_id).get());
|
||||
address_offset && stack_slot_entries.contains(*address_offset)) {
|
||||
offsets.insert(*address_offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,6 +773,8 @@ void Env::rebuild_stack_slot_use_def_info() {
|
||||
writes.at(block_id) = true;
|
||||
seen_write = true;
|
||||
}
|
||||
} else if (stack_slot_address_offset(op) == offset && !seen_write) {
|
||||
reads_before_write.at(block_id) = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -817,6 +837,13 @@ void Env::rebuild_stack_slot_use_def_info() {
|
||||
auto& info = m_stack_slot_use_def_info[RegId(Register(Reg::GPR, Reg::SP), current_var)];
|
||||
info.defs.push_back({op_id, block_id, AccessMode::WRITE, false});
|
||||
info.ssa_vars.insert(current_var);
|
||||
} else if (stack_slot_address_offset(op) == offset) {
|
||||
ASSERT(current_var != -1);
|
||||
m_stack_slot_var_by_op[op_id] = current_var;
|
||||
access_ops.push_back(op_id);
|
||||
auto& info = m_stack_slot_use_def_info[RegId(Register(Reg::GPR, Reg::SP), current_var)];
|
||||
info.uses.push_back({op_id, block_id, AccessMode::READ, false});
|
||||
info.ssa_vars.insert(current_var);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7283,8 +7283,7 @@ void ArrayFieldAccess::update_with_val(Form* new_val,
|
||||
// Reverse field lookup may already have rewritten the address expression into a dereference.
|
||||
// If its trailing tokens instantiate the indexed prefix of this access, retain that typed prefix
|
||||
// and append the fields which belong to the load itself.
|
||||
if (auto* existing = dynamic_cast<DerefElement*>(new_val->try_as_single_active_element());
|
||||
existing && !existing->is_addr_of()) {
|
||||
if (auto* existing = dynamic_cast<DerefElement*>(new_val->try_as_single_active_element())) {
|
||||
const auto& existing_tokens = existing->tokens();
|
||||
for (size_t overlap = std::min(existing_tokens.size(), m_deref_tokens.size()); overlap > 0;
|
||||
--overlap) {
|
||||
@@ -7321,8 +7320,8 @@ void ArrayFieldAccess::update_with_val(Form* new_val,
|
||||
auto combined_tokens = existing_tokens;
|
||||
combined_tokens.insert(combined_tokens.end(), m_deref_tokens.begin() + overlap,
|
||||
m_deref_tokens.end());
|
||||
result->push_back(pool.alloc_element<DerefElement>(existing->base(), existing->is_addr_of(),
|
||||
combined_tokens));
|
||||
result->push_back(
|
||||
pool.alloc_element<DerefElement>(existing->base(), false, combined_tokens));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13029,6 +13029,15 @@ buffer as two allocations in the collide-mesh category.")
|
||||
|
||||
;; - Types
|
||||
|
||||
(defenum collide-prim-id
|
||||
:type int8
|
||||
(invalid -2)
|
||||
(sphere -1)
|
||||
(group 0)
|
||||
(fg-mesh 1)
|
||||
(bg-mesh 2)
|
||||
)
|
||||
|
||||
(declare-type collide-shape-prim basic)
|
||||
(deftype collide-sticky-rider (structure)
|
||||
((rider-handle handle :offset-assert 0)
|
||||
@@ -13227,21 +13236,12 @@ past the end of the movement step." (_type_ vector) symbol) ;; 9
|
||||
(indestructible 4) ;; can't attack it.
|
||||
)
|
||||
|
||||
(defenum collide-prim-type
|
||||
:type int8
|
||||
:bitfield #t
|
||||
(bad -2)
|
||||
(unk0 0)
|
||||
(unk1 1)
|
||||
)
|
||||
|
||||
|
||||
(deftype collide-prim-core (structure)
|
||||
((world-sphere vector :inline :offset-assert 0)
|
||||
(collide-as collide-kind :offset-assert 16)
|
||||
(action collide-action :offset-assert 24)
|
||||
(offense collide-offense :offset-assert 28)
|
||||
(prim-type int8 :offset-assert 29)
|
||||
(prim-type collide-prim-id :offset-assert 29)
|
||||
(extra uint8 2 :offset-assert 30)
|
||||
(quad uint128 2 :offset 0)
|
||||
)
|
||||
@@ -13264,7 +13264,7 @@ past the end of the movement step." (_type_ vector) symbol) ;; 9
|
||||
(collide-as collide-kind :offset 32)
|
||||
(action collide-action :offset 40)
|
||||
(offense collide-offense :offset 44)
|
||||
(prim-type int8 :offset 45)
|
||||
(prim-type collide-prim-id :offset 45)
|
||||
(radius meters :offset 60)
|
||||
)
|
||||
:method-count-assert 28
|
||||
@@ -14921,6 +14921,7 @@ when hand placement and hanging clearance succeed."
|
||||
|
||||
;; - Types
|
||||
|
||||
|
||||
(deftype bsp-node (structure)
|
||||
;; A plane selects front when dot(position, plane.xyz) - plane.w is nonnegative. Positive
|
||||
;; children are bsp-node pointers; nonpositive children identify terminal sides. Visibility
|
||||
@@ -14945,7 +14946,7 @@ when hand placement and hanging clearance succeed."
|
||||
(all-visible-list (pointer uint16) :offset-assert 32)
|
||||
(visible-list-length int32 :offset-assert 36)
|
||||
(drawable-trees drawable-tree-array :offset-assert 40)
|
||||
(pat pointer :offset-assert 44)
|
||||
(pat (pointer pat-surface) :offset-assert 44)
|
||||
(pat-length int32 :offset-assert 48)
|
||||
|
||||
;; some sort of texture remapping info
|
||||
@@ -14972,8 +14973,8 @@ when hand placement and hanging clearance succeed."
|
||||
;; Packed neighboring-level flags from the terminal BSP side containing the camera.
|
||||
(current-bsp-back-flags uint32 :offset-assert 152)
|
||||
(ambients drawable-inline-array-ambient :offset-assert 156)
|
||||
(unk-data-4 float :offset-assert 160)
|
||||
(unk-data-5 float :offset-assert 164)
|
||||
(subdivide-close-distance meters :offset-assert 160)
|
||||
(subdivide-far-distance meters :offset-assert 164)
|
||||
(adgifs adgif-shader-array :offset-assert 168)
|
||||
(actor-birth-order (pointer uint32) :offset-assert 172)
|
||||
(split-box-indices (pointer uint16) :offset-assert 176)
|
||||
|
||||
@@ -17,13 +17,9 @@
|
||||
;; variation into an animation.
|
||||
|
||||
(define-extern joint-mod-look-at-handler (function cspace transformq none))
|
||||
|
||||
(define-extern joint-mod-world-look-at-handler (function cspace transformq none))
|
||||
|
||||
(define-extern joint-mod-rotate-handler (function cspace transformq none))
|
||||
|
||||
(define-extern joint-mod-joint-set-handler (function cspace transformq none))
|
||||
|
||||
(define-extern joint-mod-joint-set*-handler (function cspace transformq none))
|
||||
|
||||
;; There are several modes available for joint-mod.
|
||||
@@ -179,12 +175,15 @@
|
||||
(defmethod set-target! ((this joint-mod) (target-trans vector))
|
||||
"Set the joint-mod to look-at if we aren't in a mode, and look at the given target-trans."
|
||||
;; set mode, if we aren't in one.
|
||||
(if (= (-> this mode) (joint-mod-handler-mode reset)) (set-mode! this (joint-mod-handler-mode look-at)))
|
||||
(if (= (-> this mode) (joint-mod-handler-mode reset))
|
||||
(set-mode! this (joint-mod-handler-mode look-at)))
|
||||
;; how far are we from the target?
|
||||
(let ((distance (vector-vector-distance (-> this process root trans) target-trans)))
|
||||
(set! (-> this shutting-down?) #f)
|
||||
(vector-copy! (-> this target) target-trans)
|
||||
(if (< distance (-> this max-dist)) (set! (-> this blend) 1.0) (set! (-> this blend) 0.0)))
|
||||
(if (< distance (-> this max-dist))
|
||||
(set! (-> this blend) 1.0)
|
||||
(set! (-> this blend) 0.0)))
|
||||
0
|
||||
(none))
|
||||
|
||||
@@ -246,36 +245,42 @@
|
||||
(f0-1 (deg-diff f30-0 f0-0)))
|
||||
(if (< (-> gp-0 ignore-angle) (fabs f0-1)) (set! f0-1 0.0))
|
||||
(let ((f30-1 (fmax (fmin (* f0-1 (-> gp-0 blend) (-> gp-0 flex-blend)) (-> gp-0 twist-max y)) (- (-> gp-0 twist-max y)))))
|
||||
(if (and (-> gp-0 shutting-down?) (= (-> gp-0 twist y) f30-1)) (set-mode! gp-0 (joint-mod-handler-mode reset)))
|
||||
(if (and (-> gp-0 shutting-down?) (= (-> gp-0 twist y) f30-1))
|
||||
(set-mode! gp-0 (joint-mod-handler-mode reset)))
|
||||
(set! (-> gp-0 twist y) (deg-seek (-> gp-0 twist y) f30-1 (* 0.1 (fabs (deg-diff f30-1 (-> gp-0 twist y))))))))
|
||||
(let ((v1-15 (-> gp-0 up)))
|
||||
(cond
|
||||
((zero? v1-15) (quaternion-rotate-x! (-> xform quat) (-> xform quat) (-> gp-0 twist y)))
|
||||
((= v1-15 1) (quaternion-rotate-local-y! (-> xform quat) (-> xform quat) (-> gp-0 twist y)))
|
||||
(else (quaternion-rotate-z! (-> xform quat) (-> xform quat) (-> gp-0 twist y)))))
|
||||
(let* ((s3-1 (vector-normalize-copy! (new 'stack-no-clear 'vector)
|
||||
(the-as vector (-> gp-0 process node-list data 0 bone transform))
|
||||
1.0))
|
||||
((zero? v1-15)
|
||||
(quaternion-rotate-x! (-> xform quat) (-> xform quat) (-> gp-0 twist y)))
|
||||
((= v1-15 1)
|
||||
(quaternion-rotate-local-y! (-> xform quat) (-> xform quat) (-> gp-0 twist y)))
|
||||
(else
|
||||
(quaternion-rotate-z! (-> xform quat) (-> xform quat) (-> gp-0 twist y)))))
|
||||
(let* ((s3-1 (vector-normalize-copy! (new 'stack-no-clear 'vector) (-> gp-0 process node-list data 0 bone transform vector 0) 1.0))
|
||||
(f30-2 (vector-x-angle sv-52))
|
||||
(s3-2 (vector-flatten! (new-stack-vector0) sv-56 s3-1))
|
||||
(f0-15 (vector-x-angle s3-2))
|
||||
(f0-21 (fmax (fmin (* (- (deg-diff f30-2 f0-15)) (-> gp-0 blend) (-> gp-0 flex-blend)) (-> gp-0 twist-max x))
|
||||
(- (-> gp-0 twist-max x)))))
|
||||
(if (< (vector-dot s3-2 sv-52) 0.1) (set! f0-21 0.0))
|
||||
(if (< (vector-dot s3-2 sv-52) 0.1)
|
||||
(set! f0-21 0.0))
|
||||
(set! (-> gp-0 twist x) (deg-seek (-> gp-0 twist x) f0-21 (* 0.1 (fabs (deg-diff f0-21 (-> gp-0 twist x))))))))
|
||||
(let ((v1-27 (-> gp-0 ear)))
|
||||
(cond
|
||||
((zero? v1-27) (quaternion-rotate-x! (-> xform quat) (-> xform quat) (-> gp-0 twist x)))
|
||||
((= v1-27 1) (quaternion-rotate-local-y! (-> xform quat) (-> xform quat) (-> gp-0 twist x)))
|
||||
(else (quaternion-rotate-z! (-> xform quat) (-> xform quat) (-> gp-0 twist x)))))
|
||||
((zero? v1-27)
|
||||
(quaternion-rotate-x! (-> xform quat) (-> xform quat) (-> gp-0 twist x)))
|
||||
((= v1-27 1)
|
||||
(quaternion-rotate-local-y! (-> xform quat) (-> xform quat) (-> gp-0 twist x)))
|
||||
(else
|
||||
(quaternion-rotate-z! (-> xform quat) (-> xform quat) (-> gp-0 twist x)))))
|
||||
(cspace<-parented-transformq-joint! csp xform)
|
||||
(if (and (= (-> gp-0 process type) target) (!= (-> gp-0 blend) 0.0))
|
||||
(add-debug-text-sphere *display-target-marks*
|
||||
(bucket-id debug-no-zbuf)
|
||||
(-> gp-0 target)
|
||||
819.2
|
||||
"look"
|
||||
(new 'static 'rgba :r #xff :g #xff :a #x80))))
|
||||
(add-debug-text-sphere *display-target-marks*
|
||||
(bucket-id debug-no-zbuf)
|
||||
(-> gp-0 target)
|
||||
819.2
|
||||
"look"
|
||||
(new 'static 'rgba :r #xff :g #xff :a #x80))))
|
||||
0
|
||||
(none))
|
||||
|
||||
@@ -299,32 +304,34 @@
|
||||
(s4-2 (-> s5-0 vector 3 quad)))
|
||||
(matrix*! s5-0 s5-0 a2-3)
|
||||
(set! (-> s5-0 vector 3 quad) s4-2)))
|
||||
(let* ((s4-3 (vector-normalize-copy! (new 'stack-no-clear 'vector)
|
||||
(the-as vector (-> gp-0 process node-list data 0 bone transform))
|
||||
1.0))
|
||||
(let* ((s4-3 (vector-normalize-copy! (new 'stack-no-clear 'vector) (-> gp-0 process node-list data 0 bone transform vector 0) 1.0))
|
||||
(f30-2 (vector-x-angle sv-52))
|
||||
(s4-4 (vector-flatten! (new-stack-vector0) sv-56 s4-3))
|
||||
(f0-14 (vector-x-angle s4-4))
|
||||
(f0-20 (fmax (fmin (* (- (deg-diff f30-2 f0-14)) (-> gp-0 blend) (-> gp-0 flex-blend)) (-> gp-0 twist-max x))
|
||||
(- (-> gp-0 twist-max x)))))
|
||||
(if (< (vector-dot s4-4 sv-52) 0.1) (set! f0-20 0.0))
|
||||
(if (< (vector-dot s4-4 sv-52) 0.1)
|
||||
(set! f0-20 0.0))
|
||||
(set! (-> gp-0 twist x) (deg-seek (-> gp-0 twist x) f0-20 (fmax 1.0 (* 0.1 (fabs (deg-diff f0-20 (-> gp-0 twist x)))))))))
|
||||
(when (!= (-> gp-0 twist x) 0.0)
|
||||
(let* ((v1-20 (-> gp-0 ear))
|
||||
(a1-17 ((cond
|
||||
((zero? v1-20) matrix-rotate-x!)
|
||||
((= v1-20 1) matrix-rotate-y!)
|
||||
(else matrix-rotate-z!))
|
||||
((zero? v1-20)
|
||||
matrix-rotate-x!)
|
||||
((= v1-20 1)
|
||||
matrix-rotate-y!)
|
||||
(else
|
||||
matrix-rotate-z!))
|
||||
(new 'stack-no-clear 'matrix)
|
||||
(-> gp-0 twist x))))
|
||||
(matrix*! s5-0 a1-17 s5-0))))
|
||||
(if (and (= (-> gp-0 process type) target) (!= (-> gp-0 blend) 0.0))
|
||||
(add-debug-text-sphere *display-target-marks*
|
||||
(bucket-id debug-no-zbuf)
|
||||
(-> gp-0 target)
|
||||
819.2
|
||||
"look"
|
||||
(new 'static 'rgba :r #xff :g #xff :a #x80))))
|
||||
(add-debug-text-sphere *display-target-marks*
|
||||
(bucket-id debug-no-zbuf)
|
||||
(-> gp-0 target)
|
||||
819.2
|
||||
"look"
|
||||
(new 'static 'rgba :r #xff :g #xff :a #x80))))
|
||||
0
|
||||
(none))
|
||||
|
||||
@@ -380,7 +387,8 @@
|
||||
(quaternion-normalize! (quaternion*! (-> local-transform quat) (-> local-transform quat) (-> s5-0 quat)))
|
||||
(vector*! (-> local-transform scale) (-> local-transform scale) (-> s5-0 scale))
|
||||
(cspace<-parented-transformq-joint! node local-transform)
|
||||
(if (-> s5-0 max-dist) (set-vector! (-> node bone scale) 1.0 1.0 1.0 1.0)))
|
||||
(if (-> s5-0 max-dist)
|
||||
(set-vector! (-> node bone scale) 1.0 1.0 1.0 1.0)))
|
||||
0
|
||||
(none))
|
||||
|
||||
@@ -461,13 +469,18 @@
|
||||
(let ((v1-0 (the-as joint-mod-set-local (-> node param1))))
|
||||
(cond
|
||||
((-> v1-0 enable)
|
||||
(if (not (-> v1-0 set-translation)) (vector-copy! (-> v1-0 transform trans) (-> local-transform trans)))
|
||||
(if (not (-> v1-0 set-rotation)) (set! (-> v1-0 transform quat vec quad) (-> local-transform quat vec quad)))
|
||||
(if (not (-> v1-0 set-scale)) (vector-copy! (-> v1-0 transform scale) (-> local-transform scale)))
|
||||
(if (not (-> v1-0 set-translation))
|
||||
(vector-copy! (-> v1-0 transform trans) (-> local-transform trans)))
|
||||
(if (not (-> v1-0 set-rotation))
|
||||
(vector-copy! (-> v1-0 transform quat vec) (-> local-transform quat vec)))
|
||||
(if (not (-> v1-0 set-scale))
|
||||
(vector-copy! (-> v1-0 transform scale) (-> local-transform scale)))
|
||||
(cspace<-parented-transformq-joint! node (-> v1-0 transform)))
|
||||
(else (cspace<-parented-transformq-joint! node local-transform))))
|
||||
(else
|
||||
(cspace<-parented-transformq-joint! node local-transform))))
|
||||
(none))
|
||||
|
||||
|
||||
(defmethod new joint-mod-set-local ((allocation symbol)
|
||||
(type-to-make type)
|
||||
(process process-drawable)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(in-package goal)
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "engine/game/game-h.gc")
|
||||
|
||||
(defenum pov-camera-flag
|
||||
:bitfield #t
|
||||
:type int32
|
||||
@@ -31,7 +32,7 @@
|
||||
;; streamed animation. The broad basic type on anim-name is required to hold
|
||||
;; either form.
|
||||
(deftype pov-camera (process-drawable)
|
||||
(;; The animated camera's cspace nodes occupy the drawable root storage.
|
||||
(;; I think this field is wrong...
|
||||
(cspace-array cspace-array :overlay-at root)
|
||||
(flags pov-camera-flag)
|
||||
;; Controller aborts are ignored briefly after playback begins.
|
||||
@@ -40,7 +41,7 @@
|
||||
(notify-handle handle)
|
||||
;; A camera animation name or a spool-anim.
|
||||
(anim-name basic)
|
||||
;; Timed commands accompanying an in-memory animation.
|
||||
;; Timed commands accompanying an animation.
|
||||
(command-list pair)
|
||||
;; Processes suppressed while othercam owns the view.
|
||||
(mask-to-clear process-mask)
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
|
||||
;; Broad-phase tests use *collide-work*, which is prepared for the active cache fill.
|
||||
(define-extern collide-cache-using-line-sphere-test (function vector symbol))
|
||||
|
||||
(define-extern collide-cache-using-y-probe-test (function vector symbol))
|
||||
|
||||
(define-extern collide-cache-using-box-test (function vector symbol))
|
||||
|
||||
;; DECOMP BEGINS
|
||||
@@ -28,12 +26,14 @@
|
||||
(solid-only symbol)))
|
||||
|
||||
(deftype collide-puss-sphere (structure)
|
||||
"One query sphere and its integer-coordinate bounding box in the sphere-probe scratchpad work."
|
||||
"One query sphere and its integer-coordinate bounding box in the sphere-probe scratchpad work.
|
||||
PUSS = prim-using-spheres ?"
|
||||
((bsphere sphere :inline)
|
||||
(bbox4w bounding-box4w :inline)))
|
||||
|
||||
(deftype collide-puss-work (structure)
|
||||
"Scratchpad work for testing the cached primitives against as many as 64 query spheres."
|
||||
"Scratchpad work for testing the cached primitives against as many as 64 query spheres.
|
||||
PUSS = prim-using-spheres ?"
|
||||
((closest-pt vector :inline)
|
||||
(tri-normal vector :inline)
|
||||
(tri-bbox4w bounding-box4w :inline)
|
||||
@@ -45,7 +45,8 @@
|
||||
|
||||
(deftype collide-puyp-work (structure)
|
||||
"Working state for a downward Y probe. best-u tracks the nearest hit along move-dist and tri-out
|
||||
receives its surface, point, normal, and representative vertices."
|
||||
receives its surface, point, normal, and representative vertices.
|
||||
PUYP = prim-using-y-probe"
|
||||
((best-u float)
|
||||
(ignore-pat pat-surface)
|
||||
(tri-out collide-tri-result)
|
||||
@@ -57,8 +58,7 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(deftype collide-cache-tri (structure)
|
||||
"One world-space triangle in the collision cache. Its final quadword overlays the surface
|
||||
properties, owning primitive index, and query-specific user values."
|
||||
"One world-space triangle in the collision cache."
|
||||
((vertex vector 3 :inline) ;; actual locations
|
||||
(extra-quad uint128 :offset 48)
|
||||
(pat pat-surface :overlay-at extra-quad) ; metadata about the surface of this tri
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
;; compact vertices and strips into ordinary collision triangles. These fragments do not
|
||||
;; participate directly in the foreground collide-shape hierarchy.
|
||||
|
||||
;; Defined with the drawable methods and used by collide-frag's optional debug drawing.
|
||||
(define-extern sphere-cull (function vector symbol))
|
||||
|
||||
;; One expanded background-collision vertex.
|
||||
@@ -30,12 +29,14 @@
|
||||
(strip-data-len uint16) ;; Byte length of the strip stream, including its terminators.
|
||||
(poly-count uint16)
|
||||
(base-trans vector :inline) ;; Fixed-point translation applied while expanding vertices.
|
||||
;; These bytes occupy base-trans.w, which is not part of the XYZ translation.
|
||||
(vertex-count uint8 :overlay-at (-> base-trans w))
|
||||
(vertex-data-qwc uint8 :offset 29)
|
||||
(total-qwc uint8 :offset 30)
|
||||
(unused uint8 :offset 31)))
|
||||
|
||||
;; drawable containing a collide-fragment.
|
||||
;; These drawables are inserted into the BVH tree for broad-phase collision filtering.
|
||||
|
||||
(deftype collide-fragment (drawable)
|
||||
((mesh collide-frag-mesh :offset 8)))
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
(in-package goal)
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
|
||||
;; Collision function declarations are provided by collide-func.gc.
|
||||
;; Empty.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
;;-*-Lisp-*-
|
||||
(in-package goal)
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
|
||||
;; unused flag.
|
||||
(define *collide-test-flag* #f)
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; Foreground collision meshes belong to moving, jointed objects such as platforms. Their compact
|
||||
;; local-space vertices and triangles are transformed on demand for collision tests. Static level
|
||||
;; geometry uses collide-frag-mesh instead.
|
||||
;; local-space vertices and triangles are transformed to world-space on demand for collision tests.
|
||||
;; Static level geometry uses collide-frag-mesh instead.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;
|
||||
;; result
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
;; The triangle and contact selected by a collision test. vertex holds the three world-space
|
||||
;; corners, intersect is the closest/contact point, normal faces away from the triangle, and pat
|
||||
;; identifies the surface. Background collision tests use the same result format.
|
||||
;; identifies the surface parameters. Background collision tests use the same result format.
|
||||
(deftype collide-tri-result (structure)
|
||||
((vertex vector 3 :inline)
|
||||
(intersect vector :inline)
|
||||
@@ -38,8 +38,6 @@
|
||||
(declare-type collide-mesh-cache-tri structure)
|
||||
|
||||
;; A compact collision mesh bound to one model joint. vertex-data points to local-space positions
|
||||
;; padded through the next group of four because the transform passes always load four vectors at a
|
||||
;; time. The variable-length tris array follows the fixed header and indexes the logical positions.
|
||||
(deftype collide-mesh (basic)
|
||||
((joint-id int32)
|
||||
(num-tris uint32)
|
||||
@@ -64,9 +62,7 @@
|
||||
;; of transforming the mesh for every query. This is separate from the general collide-cache used
|
||||
;; for background and mixed collision probes.
|
||||
;;
|
||||
;; id identifies the current cache generation. Every allocation owner keeps the id with its cached
|
||||
;; triangle pointer; clearing or wrapping the cache advances id, invalidating all of those pointers
|
||||
;; without walking their owners.
|
||||
;; ID is used to invalidate the cache when the data is changed
|
||||
|
||||
;; og:preserve-this
|
||||
(defconstant COLLIDE_MESH_CACHE_SIZE #xa000)
|
||||
@@ -85,8 +81,6 @@
|
||||
(defmethod next-id! ((this collide-mesh-cache))
|
||||
"Discard all cached blocks and advance to a nonzero generation id."
|
||||
(declare (asm-func uint))
|
||||
;; Generation zero is reserved. The likely branch changes a wrapped increment to one without
|
||||
;; executing its delay instruction for the normal case.
|
||||
(rlet ((this-reg :reg a0)
|
||||
(current-id :reg v1)
|
||||
(next-id :reg v0))
|
||||
@@ -110,7 +104,7 @@
|
||||
(= (-> this id) cache-id))
|
||||
|
||||
;; Expanded cache entry: three world-space vertices, a unit normal, an integer-coordinate bounding
|
||||
;; box for fast rejection, and surface properties packed into the otherwise-unused normal.w lane.
|
||||
;; box for fast rejection, and surface properties packed into normal.w.
|
||||
(deftype collide-mesh-cache-tri (structure)
|
||||
((vertex vector 3 :inline)
|
||||
(normal vector :inline)
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
;; geometry or water.
|
||||
;;
|
||||
;; General movement queries collect background, water, and foreground primitives into collide-cache,
|
||||
;; then resolve against that common representation. Foreground mesh handling is duplicated because
|
||||
;; this path imports expanded mesh triangles into the general cache.
|
||||
;; then resolve against that common representation.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -67,7 +66,6 @@
|
||||
#f)
|
||||
|
||||
;; A collection of collide-sticky-riders
|
||||
;; dynamic type. There's one collide-sticky-rider per rider.
|
||||
(deftype collide-sticky-rider-group (basic)
|
||||
((num-riders int32)
|
||||
(allocated-riders int32)
|
||||
@@ -138,14 +136,15 @@
|
||||
((options overlaps-others-options)
|
||||
(tlist touching-list)))
|
||||
|
||||
;; The engine system is used to link collision checks with processes.
|
||||
;; This allows you to have lists of processes where the process will remove itself when it dies.
|
||||
;; The engine system is used to connect the collision system to processes with collision
|
||||
;; geometry. There are several different lists available.
|
||||
;; - hit-by-player is for things that only the player hits (powerups)
|
||||
;; - usually-hit-by-player for things that jak and others hits: crates, creatures, etc
|
||||
;; - hit-by-others is a bit weird. In practice, it's used for geometry that the camera should
|
||||
;; avoid, like doors, big platforms, etc.
|
||||
(define *collide-hit-by-player-list* (new 'global 'engine 'collide-hit-by-player-list 768))
|
||||
|
||||
(define *collide-usually-hit-by-player-list* (new 'global 'engine 'collide-usually-hit-by-player-list 256))
|
||||
|
||||
(define *collide-hit-by-others-list* (new 'global 'engine 'collide-hit-by-others-list 96))
|
||||
|
||||
(define *collide-player-list* (new 'global 'engine 'collide-player-list 32))
|
||||
|
||||
(defenum collide-list-enum
|
||||
@@ -164,17 +163,17 @@
|
||||
:type uint64
|
||||
:bitfield #t
|
||||
(background 0)
|
||||
(hit-by-player 1) ;; hit by player
|
||||
(usually-hit-by-player 2) ;; usually hit by player
|
||||
(hit-by-others 3) ;; hit by others
|
||||
(target 4) ;; target
|
||||
(hit-by-player 1)
|
||||
(usually-hit-by-player 2)
|
||||
(hit-by-others 3)
|
||||
(target 4)
|
||||
(water 5)
|
||||
(powerup 6)
|
||||
(crate 7)
|
||||
(enemy 8) ;; also used for powerups
|
||||
(wall-object 9) ;; also object. door, pusher (blockers?)
|
||||
(projectile 10)
|
||||
(ground-object 11) ;; object, like darkecobarray, platforms
|
||||
(ground-object 11) ;; object, platforms
|
||||
(target-attack 12) ;; all target attacks
|
||||
(mother-spider 13)
|
||||
(cak-14 14) ;; unused
|
||||
@@ -262,6 +261,17 @@
|
||||
(indestructible 4) ;; can't attack it.
|
||||
)
|
||||
|
||||
;; Identification of prim type
|
||||
(defenum collide-prim-id
|
||||
:type int8
|
||||
(invalid -2) ;; error
|
||||
(sphere -1)
|
||||
(group 0)
|
||||
(fg-mesh 1)
|
||||
(bg-mesh 2) ;; used for meshes faked through water/background
|
||||
)
|
||||
|
||||
|
||||
;; Every primitive has a prim-core.
|
||||
;; this is a 32-byte chunk of data that can be pulled out an put in collide caches
|
||||
;; it stores the transformed world sphere and the collision settings
|
||||
@@ -270,22 +280,23 @@
|
||||
(collide-as collide-kind)
|
||||
(action collide-action)
|
||||
(offense collide-offense)
|
||||
(prim-type int8)
|
||||
(prim-type collide-prim-id)
|
||||
(extra uint8 2)
|
||||
(quad uint128 2 :overlay-at (-> world-sphere quad))))
|
||||
|
||||
(declare-type collide-shape basic)
|
||||
|
||||
(declare-type collide-cache-prim structure)
|
||||
|
||||
(declare-type collide-shape-prim-group basic)
|
||||
|
||||
(declare-type collide-cache basic)
|
||||
|
||||
|
||||
;; the base class for collision shapes.
|
||||
(deftype collide-shape-prim (basic)
|
||||
((cshape collide-shape)
|
||||
(prim-id uint32)
|
||||
;; -2 : local-sphere is relative to cshape
|
||||
;; -1 : user is responsible for setting world-sphere
|
||||
;; 0+: use bone translation
|
||||
(transform-index int8)
|
||||
(prim-core collide-prim-core :inline)
|
||||
(local-sphere vector :inline)
|
||||
@@ -294,7 +305,7 @@
|
||||
(collide-as collide-kind :overlay-at (-> prim-core collide-as))
|
||||
(action collide-action :overlay-at (-> prim-core action))
|
||||
(offense collide-offense :overlay-at (-> prim-core offense))
|
||||
(prim-type int8 :overlay-at (-> prim-core prim-type))
|
||||
(prim-type collide-prim-id :overlay-at (-> prim-core prim-type))
|
||||
(radius meters :overlay-at (-> local-sphere w)))
|
||||
(:methods
|
||||
(new (symbol type collide-shape uint int) _type_)
|
||||
@@ -327,7 +338,7 @@
|
||||
|
||||
;; sphere collision
|
||||
;; the pat is stored directly here.
|
||||
;; I believe the "local sphere" is used as the sphere.
|
||||
;; The "local sphere" is used as the sphere geometry.
|
||||
(deftype collide-shape-prim-sphere (collide-shape-prim)
|
||||
((pat pat-surface))
|
||||
(:methods
|
||||
@@ -335,8 +346,9 @@
|
||||
|
||||
;; mesh collision
|
||||
;; the pats are stored per tri in the mesh.
|
||||
;; These meshes interact with a cache automatically (a specific collide-shape-prim-mesh cache, not the
|
||||
;; more general collide-cache)
|
||||
;; For direct collision queries (not through collide-cache), these
|
||||
;; get unpacked into a separate mesh-cache that holds only
|
||||
;; a single mesh.
|
||||
(deftype collide-shape-prim-mesh (collide-shape-prim)
|
||||
((mesh collide-mesh)
|
||||
(mesh-id int32)
|
||||
@@ -363,11 +375,14 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; This is sort of the "parent" of all collide prims for a process-drawable.
|
||||
;; Each process-drawable (pd) should have one collide-shape, which is often the root.
|
||||
;; Each process-drawable (pd) can have one collide-shape.
|
||||
;; It represents:
|
||||
;; - the location of the thing in the world
|
||||
;; - settings abouts collision/navigation
|
||||
;; - riders
|
||||
;; since collide-shape is a child of trsqv, it can overlay
|
||||
;; the existing "root" field, so its position simultaneously sets
|
||||
;; the process location for drawing, collision, and gameplay logic.
|
||||
|
||||
(declare-type collide-work structure)
|
||||
|
||||
@@ -385,7 +400,7 @@
|
||||
(navf6 6)
|
||||
(navf7 7))
|
||||
|
||||
;; we're a child of trsqv, so we store a full transform + derivative.
|
||||
;; we're a child of trsqv, so we store a full transform + velocity.
|
||||
(deftype collide-shape (trsqv)
|
||||
((process process-drawable)
|
||||
(max-iteration-count uint8)
|
||||
@@ -536,7 +551,7 @@
|
||||
(csrf30)
|
||||
(csrf31))
|
||||
|
||||
;; A collide-shape for independently moving objects
|
||||
;; A collide-shape for independently moving objects.
|
||||
(deftype collide-shape-moving (collide-shape)
|
||||
((rider-time time-frame)
|
||||
(rider-last-move vector :inline)
|
||||
@@ -589,7 +604,7 @@
|
||||
(set! (-> this collide-with) (collide-kind))
|
||||
(set! (-> this transform-index) -2)
|
||||
(set! (-> this prim-core offense) (collide-offense no-offense))
|
||||
(set! (-> this prim-core prim-type) -2)
|
||||
(set! (-> this prim-core prim-type) (collide-prim-id invalid))
|
||||
this))
|
||||
|
||||
(defmethod new collide-shape-prim-sphere ((allocation symbol) (type-to-make type) (cshape collide-shape) (prim-id uint))
|
||||
@@ -597,7 +612,7 @@
|
||||
(let ((this (the collide-shape-prim-sphere
|
||||
((method-of-type collide-shape-prim new) allocation type-to-make cshape prim-id (size-of collide-shape-prim-sphere)))))
|
||||
(set! (-> this pat) (new 'static 'pat-surface :mode (pat-mode obstacle)))
|
||||
(set! (-> this prim-core prim-type) -1)
|
||||
(set! (-> this prim-core prim-type) (collide-prim-id sphere))
|
||||
this))
|
||||
|
||||
(defmethod new collide-shape-prim-mesh ((allocation symbol) (type-to-make type) (cshape collide-shape) (mesh-id uint) (prim-id uint))
|
||||
@@ -607,7 +622,7 @@
|
||||
(set! (-> this mesh) #f)
|
||||
(set! (-> this mesh-id) (the-as int mesh-id))
|
||||
(set! (-> this mesh-cache-id) (the-as uint 0))
|
||||
(set! (-> this prim-core prim-type) 1)
|
||||
(set! (-> this prim-core prim-type) (collide-prim-id fg-mesh))
|
||||
(the-as collide-shape-prim-mesh this)))
|
||||
|
||||
(defmethod new collide-shape-prim-group ((allocation symbol) (type-to-make type) (cshape collide-shape) (element-count uint) (prim-id int))
|
||||
@@ -621,7 +636,7 @@
|
||||
(the int (+ (-> type-to-make size) (* (+ element-count -1) 4)))))))
|
||||
(set! (-> this allocated-prims) (the int element-count))
|
||||
(set! (-> this num-prims) 0)
|
||||
(set! (-> this prim-core prim-type) 0)
|
||||
(set! (-> this prim-core prim-type) (collide-prim-id group))
|
||||
(while (nonzero? element-count)
|
||||
(+! element-count -1)
|
||||
(set! (-> this prims element-count) #f)
|
||||
@@ -647,6 +662,7 @@
|
||||
(set! (-> this event-other) #f)
|
||||
(set! (-> this riders) #f)
|
||||
(set! (-> this root-prim) #f)
|
||||
;; ignore the appropriate PATs
|
||||
(case (-> proc type symbol)
|
||||
(('camera) (set! (-> this pat-ignore-mask) (new 'static 'pat-surface :nocamera #x1)))
|
||||
(else (set! (-> this pat-ignore-mask) (new 'static 'pat-surface :noentity #x1))))
|
||||
@@ -680,6 +696,7 @@
|
||||
"Return the header size plus storage for the allocated rider capacity."
|
||||
(the-as int (+ (-> this type size) (* (+ (-> this allocated-riders) -1) 32))))
|
||||
|
||||
;; Fake collide-shape-prim for collisions generated from the background.
|
||||
(define *collide-shape-prim-backgnd*
|
||||
(new 'static
|
||||
'collide-shape-prim-mesh
|
||||
@@ -692,7 +709,7 @@
|
||||
:collide-as (collide-kind background)
|
||||
:action (collide-action solid)
|
||||
:offense (collide-offense indestructible)
|
||||
:prim-type 2)
|
||||
:prim-type (collide-prim-id bg-mesh))
|
||||
:local-sphere
|
||||
(new 'static 'vector :w 204800000.0)
|
||||
:mesh #f))
|
||||
@@ -709,7 +726,7 @@
|
||||
:collide-as (collide-kind water)
|
||||
:action (collide-action solid)
|
||||
:offense (collide-offense indestructible)
|
||||
:prim-type 2)
|
||||
:prim-type (collide-prim-id bg-mesh))
|
||||
:local-sphere
|
||||
(new 'static 'vector :w 204800000.0)
|
||||
:mesh #f))
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; target-collision-reaction records the result of each collision frame in a 128-entry ring.
|
||||
;; An entry keeps the contact point, final position, incoming and outgoing velocity, contact
|
||||
;; normals, collision state, reaction flags, surface properties, and time. Airborne frames get
|
||||
;; a minimal entry so readers can walk the ring without losing the frame sequence.
|
||||
;; History of collision from target, used for debugging.
|
||||
(deftype collide-history (structure)
|
||||
((intersect vector :inline)
|
||||
(trans vector :inline)
|
||||
@@ -23,10 +20,7 @@
|
||||
(:methods
|
||||
(update! (_type_ collide-shape-moving vector vector vector) _type_)))
|
||||
|
||||
;; Jak's collision shape and movement state. The control frame rotates world velocity into Jak's
|
||||
;; facing frame so thrust, gravity, and surface response can be applied consistently before the
|
||||
;; velocity is rotated back to world space. The remainder of the type carries input, contact
|
||||
;; probes, attack state, edge-grab state, shared state-machine scratch, and collision history.
|
||||
;; Jak's collision shape and movement state.
|
||||
;;
|
||||
;; state-var0/1/2 and state-vector0/1 are deliberately shared between target states. The named
|
||||
;; overlays select the interpretation used by each state. saved-launch-event through
|
||||
@@ -118,7 +112,6 @@
|
||||
(danger-sphere0 collide-shape-prim-sphere :offset 1632)
|
||||
(danger-sphere1 collide-shape-prim-sphere :offset 1636)
|
||||
(danger-sphere2 collide-shape-prim-sphere :offset 1640)
|
||||
;; Move cooldowns, body attachments, and velocity history.
|
||||
(wheel-counter int32 :offset 1656)
|
||||
(last-wheel-end-time time-frame :offset 1664)
|
||||
(last-running-attack-end-time time-frame :offset 1672)
|
||||
@@ -142,7 +135,6 @@
|
||||
(transv-history vector 16 :inline :offset 1856)
|
||||
(average-xz-vel float :offset 2112)
|
||||
(idx-of-fastest-xz-vel int32 :offset 2116)
|
||||
;; Edge-grab and per-state data.
|
||||
(hand-to-edge-dist float :offset 2120)
|
||||
(edge-grab-edge-dir vector :inline :offset 2128)
|
||||
(edge-grab-across-edge-dir vector :inline :offset 2144)
|
||||
@@ -179,7 +171,6 @@
|
||||
(launch-camera-state int64 :offset 2440)
|
||||
(launch-dest int64 :offset 2448)
|
||||
(launch-tracking-time int64 :offset 2456)
|
||||
;; Collision history and the PAL-expanded tail.
|
||||
(history-data-idx int16 :offset 2488)
|
||||
(history-length int16 :offset 2490)
|
||||
(history-data collide-history 128 :inline)
|
||||
@@ -202,9 +193,7 @@
|
||||
(unknown-int36 int32 :offset 19000)))
|
||||
|
||||
(defmethod update! ((this collide-history) (shape collide-shape-moving) (intersect vector) (incoming-velocity vector) (outgoing-velocity vector))
|
||||
"Record a collision-history sample, including the contact point, final position,
|
||||
incoming and outgoing velocity, contact normals, collision state, reaction flags, surface
|
||||
properties, and the current time."
|
||||
"Record a collision-history sample."
|
||||
(vector-copy! (-> this intersect) intersect)
|
||||
(vector-copy! (-> this transv) incoming-velocity)
|
||||
(vector-copy! (-> this transv-out) outgoing-velocity)
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
(in-package goal)
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "engine/math/math.gc")
|
||||
|
||||
;; PAT packs the collision behavior of each mesh triangle into one 32-bit word.
|
||||
;; The low three skip bits can exclude the triangle from entity, camera, or edge
|
||||
;; queries. Mode classifies its collision response, material selects movement,
|
||||
;; sound, and particle effects, camera holds camera-query flags, and event selects
|
||||
;; a contact hazard.
|
||||
|
||||
(defenum pat-material
|
||||
:type uint8
|
||||
(stone)
|
||||
@@ -46,12 +53,6 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; PAT packs the collision behavior of each mesh triangle into one 32-bit word.
|
||||
;; The low three skip bits can exclude the triangle from entity, camera, or edge
|
||||
;; queries. Mode classifies its collision response, material selects movement,
|
||||
;; sound, and particle effects, camera holds camera-query flags, and event selects
|
||||
;; a contact hazard.
|
||||
|
||||
(deftype pat-surface (uint32)
|
||||
((skip uint8 :offset 0 :size 3) ;; combined collision-query skip mask
|
||||
(mode pat-mode :offset 3 :size 3)
|
||||
@@ -62,8 +63,7 @@
|
||||
(nocamera uint8 :offset 1 :size 1) ;; exclude from camera collision queries
|
||||
(noedge uint8 :offset 2 :size 1) ;; exclude from edge queries
|
||||
(nolineofsight uint8 :offset 12 :size 1) ;; exclude from camera line-of-sight queries
|
||||
;; Ignore endless-fall contacts. This overlaps bit 1 of event because ignore
|
||||
;; masks use the same packed bit positions as triangle PAT values.
|
||||
;; Ignore endless-fall contacts.
|
||||
(noendlessfall uint8 :offset 15 :size 1)))
|
||||
|
||||
(defun-debug pat-material->string ((pat pat-surface))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(in-package goal)
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "kernel/gcommon.gc")
|
||||
|
||||
(defenum surface-flags
|
||||
:bitfield #t
|
||||
:type uint32
|
||||
@@ -22,10 +23,10 @@
|
||||
(prevent-jump)
|
||||
;; target is launch jumping (from a blue eco pad)
|
||||
(prevent-attacks-during-launch-jump)
|
||||
;; never set by any shipped surface, but tested together with the launch-jump bit:
|
||||
;; never set by any surface, but tested together with the launch-jump bit:
|
||||
;; blocks square/"hands" attacks, including the flop out of jump states
|
||||
(prevent-hand-attack)
|
||||
;; never set by a shipped surface; blocks circle/"feet" spin attacks
|
||||
;; never set by any surface; blocks circle/"feet" spin attacks
|
||||
(prevent-feet-attack)
|
||||
(allow-edge-grab) ;; if set, and jak is falling, turn on the ledge grab search.
|
||||
(jump) ;; set on all jumps, used to prevent "on-grounds" in places
|
||||
@@ -48,7 +49,7 @@
|
||||
(turnv float) ;; maximum rate for turning the facing direction
|
||||
(turnvv float) ;; maximum rate for steering the target direction
|
||||
(tiltv float) ;; maximum rate for leaning toward the surface normal
|
||||
(tiltvv float)
|
||||
(tiltvv float) ;; unused
|
||||
(transv-max float) ;; hard speed limit
|
||||
(target-speed float) ;; full-stick speed that acceleration seeks
|
||||
(seek0 float) ;; acceleration with input aligned to motion
|
||||
@@ -79,18 +80,18 @@
|
||||
|
||||
;; these calc-terminal functions are unused.
|
||||
(defun calc-terminal-vel ((acceleration float) (constant-drag float) (drag-coefficient float))
|
||||
"Compute the fixed-point velocity for the legacy linear drag equation from per-second
|
||||
"Compute the final velocity for the legacy linear drag equation from per-second
|
||||
acceleration, constant drag, and the linear drag coefficient."
|
||||
(- (* (/ (- (/ acceleration 60) constant-drag) drag-coefficient) (- 1.0 drag-coefficient)) constant-drag))
|
||||
|
||||
(defun calc-terminal2-vel ((acceleration float) (constant-drag float) (drag-coefficient float) (reserved float))
|
||||
"Compute the fixed-point velocity for the legacy quadratic drag equation.
|
||||
"Compute the final velocity for the legacy quadratic drag equation.
|
||||
reserved is accepted by the original interface but is not used."
|
||||
(let ((speed (sqrtf (/ (- (/ acceleration 60) constant-drag) drag-coefficient))))
|
||||
(- speed (+ constant-drag (* drag-coefficient (square speed))))))
|
||||
|
||||
(defun calc-terminal4-vel ((acceleration float) (constant-drag float) (drag-coefficient float))
|
||||
"Compute the fixed-point velocity for the legacy fourth-power drag equation from
|
||||
"Compute the final velocity for the legacy fourth-power drag equation from
|
||||
per-second acceleration, constant drag, and the drag coefficient."
|
||||
(let ((speed (sqrtf (sqrtf (/ (- (/ acceleration 60) constant-drag) drag-coefficient)))))
|
||||
(- speed (+ constant-drag (* drag-coefficient (* (square speed) speed speed))))))
|
||||
@@ -158,6 +159,7 @@
|
||||
|
||||
;; The common surfaces:
|
||||
|
||||
;; modifiers during normal walking/running/standing.
|
||||
(define *walk-mods*
|
||||
(new 'static
|
||||
'surface
|
||||
@@ -186,6 +188,8 @@
|
||||
:align-speed 1.0
|
||||
:flags (surface-flags allow-look-around)))
|
||||
|
||||
;; modifiers during punch attack, turnv/turnvv are zero, locking in
|
||||
;; the punch direction
|
||||
(define *walk-no-turn-mods*
|
||||
(new 'static
|
||||
'surface
|
||||
@@ -211,6 +215,7 @@
|
||||
:slope-up-traction 1.0
|
||||
:align-speed 1.0))
|
||||
|
||||
;; modifiers during the "turn around" animation.
|
||||
(define *turn-around-mods*
|
||||
(new 'static
|
||||
'surface
|
||||
@@ -233,6 +238,7 @@
|
||||
:slope-up-traction 1.0
|
||||
:align-speed 1.0))
|
||||
|
||||
;; slower "duck" crawling walk
|
||||
(let ((a0-3 (new 'static
|
||||
'surface
|
||||
:name 'duck
|
||||
@@ -263,6 +269,7 @@
|
||||
;; og:preserve-this
|
||||
(define *duck-mods* a0-3))
|
||||
|
||||
;; unused.
|
||||
(define *duck-attack-mods*
|
||||
(new 'static
|
||||
'surface
|
||||
@@ -290,6 +297,7 @@
|
||||
:mode 'attack
|
||||
:flags (surface-flags attacking ducking)))
|
||||
|
||||
;; modifiers for jump
|
||||
(define *jump-mods*
|
||||
(new 'static
|
||||
'surface
|
||||
@@ -319,6 +327,7 @@
|
||||
:mode 'air
|
||||
:flags (surface-flags allow-edge-grab jump)))
|
||||
|
||||
;; modifiers for jump
|
||||
(define *double-jump-mods*
|
||||
(new 'static
|
||||
'surface
|
||||
|
||||
@@ -2,29 +2,20 @@
|
||||
(in-package goal)
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "engine/game/game-h.gc")
|
||||
|
||||
(define-extern mistycam-spawn (function none))
|
||||
|
||||
(define-extern beachcam-spawn (function none))
|
||||
|
||||
(declare-type camera-tracker process)
|
||||
|
||||
(define-extern process-grab? (function process symbol :behavior camera-tracker))
|
||||
|
||||
(define-extern process-release? (function process symbol :behavior process))
|
||||
|
||||
(define-extern fuel-cell type)
|
||||
|
||||
(define-extern birth-pickup-at-point
|
||||
(function vector pickup-type float symbol process-tree fact-info (pointer process) :behavior process))
|
||||
|
||||
(declare-type collide-shape trsqv)
|
||||
|
||||
(declare-type collide-shape-moving collide-shape)
|
||||
|
||||
(declare-type sparticle-launch-group basic)
|
||||
|
||||
(declare-type part-tracker process)
|
||||
|
||||
(declare-type collide-prim-core structure)
|
||||
|
||||
(define-extern part-tracker-init
|
||||
@@ -39,11 +30,8 @@
|
||||
part-tracker))
|
||||
|
||||
(declare-type touch-tracker process-drawable)
|
||||
|
||||
(define-extern touch-tracker-init (function vector float time-frame none :behavior touch-tracker))
|
||||
|
||||
(define-extern eco-blue-glow (function vector none))
|
||||
|
||||
(declare-type joint-mod basic)
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
(require "engine/gfx/hw/display-h.gc")
|
||||
(require "engine/anim/joint-h.gc")
|
||||
(require "engine/game/game-h.gc")
|
||||
|
||||
(define-extern cspace-index-by-name (function process-drawable string int))
|
||||
|
||||
(define-extern cspace-by-name (function process-drawable string cspace))
|
||||
|
||||
(define-extern joint-control-reset! (function joint-control joint-control-channel none :behavior process-drawable))
|
||||
|
||||
(defun cspace-by-name-no-fail ((drawable process-drawable) (name string))
|
||||
@@ -93,8 +92,7 @@
|
||||
lets callers hold an animation on an explicitly selected frame."
|
||||
(-> channel frame-num))
|
||||
|
||||
;; Persistent actor state carried between births. A try reset clears #x26f, a full game reset
|
||||
;; clears #x77f, and force-birth survives both.
|
||||
;; Persistent actor state carried between births.
|
||||
(defenum entity-perm-status
|
||||
:bitfield #t
|
||||
:type uint16
|
||||
@@ -116,10 +114,11 @@
|
||||
Joint-animation recipe for creatures
|
||||
------------------------------------
|
||||
|
||||
The `ja` helpers operate on `self`'s joint controller. A channel has an animation group, an
|
||||
internal frame, a frame interpolation value, and a frame-number function. Channel zero is the
|
||||
ordinary whole-creature animation; use another channel only when the creature's skeleton and art
|
||||
were authored for a layered animation.
|
||||
The `ja` helpers operate on a process's joint controller.
|
||||
The controller tracks multiple "channels", which can be blended together to layer or fade
|
||||
animations.
|
||||
Each channel knows the animation, the progress, and has a num-func to produce the next frame
|
||||
index.
|
||||
|
||||
Choose the animation with `:group!`, and choose how its frame changes with `:num!`:
|
||||
|
||||
@@ -133,41 +132,40 @@ Choose the animation with `:group!`, and choose how its frame changes with `:num
|
||||
|
||||
The speed defaults to 1.0. `seek!` also defaults its target to the animation's last internal
|
||||
frame, so `(seek!)` is the usual one-shot. `ja-aframe` converts an artist's timeline frame to the
|
||||
internal frame used by `seek!`; use it for authored contacts, anticipation poses, and handoffs.
|
||||
internal frame used by `seek!`.
|
||||
|
||||
`ja` applies the requested changes and, when `:num!` selects a frame rule, evaluates the channel
|
||||
immediately. Direct field changes such as `:group!`, `:num-func`, and `:frame-num` can be combined
|
||||
to prepare a pose without advancing it. `ja-no-eval` also suppresses the evaluation attached to
|
||||
`:num!`; that is useful immediately before pushing a blend, or when the caller needs to evaluate
|
||||
the old stack explicitly with `ja-blend-eval`.
|
||||
immediately. Setting `:group!`, `:num-func`, and/or `:frame-num` without `:num!` won't evaluate.
|
||||
`ja-no-eval` can be used to suppresses evaluation even when a new num-func is set with `:num!`.
|
||||
That is useful when something else will evaluate later and you want to avoid evaluating twice.
|
||||
|
||||
`ja-play` is the standard blocking one-shot: it installs the group and frame rule without an
|
||||
initial evaluation, then suspends once per frame and advances until a seek reaches its target.
|
||||
Forms in its body run before each suspension, which is where a creature should steer, align root
|
||||
motion, or evaluate the channels underneath a blend.
|
||||
`ja-play` is a blocking playback macro: it sets up an animation and runs code in the body until
|
||||
the animation is done.
|
||||
|
||||
For a clean transition, call `ja-channel-push!` before selecting the new group. It keeps the old
|
||||
pose below a new root group and fades it out over the supplied time. During a hand-authored
|
||||
transition, call `ja-blend-eval` while the new animation plays so the retained pose stays current.
|
||||
Use `ja-group?` to select animation-specific handoffs rather than restarting a generic pose.
|
||||
anim below a new root anim and fades it out over the supplied time. During a hand-authored
|
||||
transition, call `ja-blend-eval` while the new animation plays so the old animation is updated.
|
||||
|
||||
Typical creature loops are:
|
||||
|
||||
;; A looping locomotion cycle.
|
||||
;; make the current animation fade out over 0.15 seconds
|
||||
(ja-channel-push! 1 (seconds 0.15))
|
||||
;; install the new main animation of run, starting at min frame
|
||||
(ja :group! creature-run-ja :num! min)
|
||||
;; run the run animation in a loop.
|
||||
;; evaluation will handle dropping the old animation automatically.
|
||||
(loop
|
||||
(suspend)
|
||||
(ja :num! (loop! run-speed)))
|
||||
|
||||
;; A one-shot action with steering while it plays.
|
||||
;; A second example: A one-shot attack animation with steering while it plays.
|
||||
;; fade out old anim
|
||||
(ja-channel-push! 1 (seconds 0.1))
|
||||
;; play and steer until attack-ja is done.
|
||||
(ja-play :group! creature-attack-ja :num! (seek!) :frame-num 0.0
|
||||
(turn-toward-target! self))
|
||||
|
||||
Keep `:frame-num 0.0` on a newly selected one-shot unless the action deliberately joins at a
|
||||
specific authored pose. A polished creature should blend into new groups, use artist frames for
|
||||
visual beats, and make its locomotion speed explicit so motion and animation remain in step.
|
||||
|#
|
||||
|
||||
(defmacro ja-group (&key (chan 0))
|
||||
|
||||
@@ -7,11 +7,8 @@
|
||||
(define-extern *debug-menu-context* debug-menu-context)
|
||||
|
||||
(define-extern add-debug-matrix (function symbol bucket-id matrix matrix))
|
||||
|
||||
(define-extern add-debug-text-sphere (function symbol bucket-id vector float string rgba symbol))
|
||||
|
||||
(define-extern add-debug-line (function symbol bucket-id vector vector rgba symbol rgba symbol))
|
||||
|
||||
(defun-extern add-debug-sphere symbol bucket-id vector float rgba symbol)
|
||||
|
||||
;; DECOMP BEGINS
|
||||
@@ -26,18 +23,15 @@
|
||||
(h-first int32)
|
||||
(h-last int32)))
|
||||
|
||||
;; Compact vertex snapshot used by the debug vertex statistics display. It keeps
|
||||
;; transformed coordinates, a packed normal, texture coordinates, and color in
|
||||
;; the same 32-byte record.
|
||||
;; Compact vertex snapshot used by the debug vertex statistics display. It contains
|
||||
;; transformed coordinates, a packed normal, texture coordinates, and color.
|
||||
(deftype debug-vertex (structure)
|
||||
((trans vector4w :inline)
|
||||
(normal vector3h :inline)
|
||||
(st vector2h :inline)
|
||||
(color uint32)))
|
||||
|
||||
;; Debug geometry statistics and storage for up to 600 captured vertex records.
|
||||
;; The custom inspector in debug.gc prints the active records and their packed
|
||||
;; attributes.
|
||||
;; Storage for debug-vertices. Not sure why it's called "stats".
|
||||
(deftype debug-vertex-stats (basic)
|
||||
((length int32)
|
||||
(pos-count int32)
|
||||
|
||||
@@ -23,10 +23,11 @@
|
||||
(cycles-instructions 0)
|
||||
(icache-dcache 1))
|
||||
|
||||
;; One renderer bucket is sampled at a time. select chooses either cycles/instructions or
|
||||
;; One statistic group in one category is sampled at a time.
|
||||
;; select chooses either cycles/instructions or
|
||||
;; instruction-cache/data-cache events, ctrl is the corresponding EE Perf register value, and
|
||||
;; accum0/accum1 collect the raw counter pair until the end-of-frame code assigns the named totals.
|
||||
;; The explicit wait totals account for stalls that the event counters do not describe directly.
|
||||
;; The explicit wait totals are incremented by the engine code when waiting for DMA completion.
|
||||
(deftype perf-stat (structure)
|
||||
((frame-number uint32)
|
||||
(count uint32)
|
||||
@@ -52,7 +53,6 @@
|
||||
(deftype perf-stat-array (inline-array-class)
|
||||
((data perf-stat :inline :dynamic)))
|
||||
|
||||
;; perf-stat is exactly 52 bytes; inline arrays use that as their dynamic element stride.
|
||||
(set! (-> perf-stat-array heap-base) (the-as uint 52))
|
||||
|
||||
(#unless PC_PORT
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
|
||||
(defconstant MATRIX_ENGINE_AMOUNT (* 1024 PROCESS_HEAP_MULT))
|
||||
|
||||
;; Draw connections for the current level background.
|
||||
;; Holds the bsp of each level that's current loaded, consumed by
|
||||
;; background renderers.
|
||||
(define *background-draw-engine* (new 'global 'engine 'draw 10))
|
||||
|
||||
;; The matrix engine is a per-frame queue of process handles rather than an engine.
|
||||
|
||||
@@ -4,34 +4,34 @@
|
||||
(require "engine/entity/res-h.gc")
|
||||
(require "kernel/gcommon.gc")
|
||||
(require "engine/util/types-h.gc")
|
||||
|
||||
;; Level data contains a list of "entity" objects.
|
||||
;; An entity-actor tells the game engine to spawn a process of a certain type with
|
||||
;; certain parameters.
|
||||
;; An entity-camera is a region with predefined camera setings
|
||||
;; An entity-ambient is a region with some game setting like music/rendering changes.
|
||||
|
||||
(defun-extern entity-by-name string entity)
|
||||
|
||||
(defun-extern entity-by-type type entity-actor)
|
||||
|
||||
(defun-extern entity-by-aid uint entity)
|
||||
|
||||
(define-extern reset-actors (function symbol none))
|
||||
|
||||
(define-extern *spawn-actors* symbol)
|
||||
|
||||
;; TODO - for cam-start
|
||||
(define-extern reset-cameras (function none))
|
||||
|
||||
(define-extern process-by-ename (function string process))
|
||||
|
||||
(define-extern entity-birth-no-kill (function entity none))
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; toggles for generating actor visibility data.
|
||||
;; a somewhat broken feature for computing the bounding box of where an actor can
|
||||
;; be based on watching where it goes.
|
||||
(define *generate-actor-vis* #f)
|
||||
|
||||
(define *generate-actor-vis-start* #f)
|
||||
|
||||
(define *generate-actor-vis-output* #f)
|
||||
|
||||
;; Sixteen bytes of persistent per-entity state. The first eight bytes are available to each actor
|
||||
;; type, followed by lifecycle flags, task ownership, and the actor id. The quad overlay supports
|
||||
;; copying the complete record to and from save and level storage.
|
||||
;; Sixteen bytes of persistent per-entity state.
|
||||
;; The first 8 are user-defined, and the last 8 have shared meanings.
|
||||
(deftype entity-perm (structure)
|
||||
((user-object object 2)
|
||||
(user-uint64 uint64 :overlay-at (-> user-object 0))
|
||||
@@ -51,8 +51,8 @@
|
||||
(:methods
|
||||
(update-perm! (_type_ symbol entity-perm-status) _type_)))
|
||||
|
||||
;; Runtime link between a static entity resource and its live process. Level lists use prev-link
|
||||
;; and next-link; trans and perm remain available while the process is absent.
|
||||
;; Runtime link between a static entity resource and its live process.
|
||||
;; prev-link and next-link iterate through the links in a level's entity list.
|
||||
(deftype entity-links (structure)
|
||||
((prev-link entity-links)
|
||||
(next-link entity-links)
|
||||
@@ -92,8 +92,7 @@
|
||||
(deftype entity-camera (entity)
|
||||
((quat quaternion :inline)))
|
||||
|
||||
;; Type-specific ambient state. The first twelve bytes are a compact payload interpreted by the
|
||||
;; function in the final word.
|
||||
;; ambient parameters, very flexible.
|
||||
(deftype entity-ambient-data (structure)
|
||||
((user-object object 3)
|
||||
(function (function drawable-ambient vector none))
|
||||
@@ -112,19 +111,21 @@
|
||||
|
||||
(set! (-> entity-ambient-data-array heap-base) (the-as uint 16))
|
||||
|
||||
;; placement of an ambient.
|
||||
(deftype entity-ambient (entity)
|
||||
((ambient-data entity-ambient-data :overlay-at extra))
|
||||
(:methods
|
||||
(draw-debug (_type_) none)
|
||||
(birth-ambient! (_type_) none)))
|
||||
|
||||
;; An entity that can own a live actor process, navigation mesh, visibility id, task, and
|
||||
;; orientation.
|
||||
;; A placed entity. This inherits position and res-lump settings from
|
||||
;; the parent type and adds in the info needed to spawn an actor.
|
||||
;; putting nav-mesh in the entity base type is a bit odd.
|
||||
(deftype entity-actor (entity)
|
||||
((nav-mesh nav-mesh)
|
||||
(etype type)
|
||||
(task game-task)
|
||||
(vis-id uint16)
|
||||
(etype type) ;; type of process to spawn
|
||||
(task game-task) ;; associated task
|
||||
(vis-id uint16) ;; visibility ID
|
||||
(vis-id-signed int16 :overlay-at vis-id)
|
||||
(quat quaternion :inline))
|
||||
(:methods
|
||||
@@ -134,6 +135,8 @@
|
||||
(set-or-clear-status! (_type_ entity-perm-status symbol) none)))
|
||||
|
||||
;; Actor creation table entry: process type, load dependencies, pool, and per-process heap size.
|
||||
;; This is only needed to override the defaults, which is usually only done to change process
|
||||
;; pool settings or heap sizes.
|
||||
(deftype entity-info (basic)
|
||||
((ptype type)
|
||||
(package basic)
|
||||
@@ -141,10 +144,8 @@
|
||||
(pool basic)
|
||||
(heap-size int32)))
|
||||
|
||||
;; Navigation supplies this function later in the load order. Until then entity login has a harmless
|
||||
;; default.
|
||||
(define-extern entity-nav-login (function entity-actor none))
|
||||
|
||||
;; default entity-nav-login for now... a little suspicious that this is needed
|
||||
(if (zero? entity-nav-login) (set! entity-nav-login (the-as (function entity-actor none) nothing)))
|
||||
|
||||
;; Dynamic actor population limits. Processes pause outside pause-dist, eligible entities can be
|
||||
|
||||
@@ -115,8 +115,8 @@ This system grew out of the Crash 2 entity resource system.
|
||||
interpolation endpoint. Return a negative packed result when the property or requested
|
||||
sample is missing."
|
||||
(local-vars (tag-idx int))
|
||||
;; These names belong to the fixed entity record and must not enter generic
|
||||
;; property lookup.
|
||||
;; These values are stored in the entity type directly. They might have been part of
|
||||
;; the lump properties in an earlier version.
|
||||
(when (or (= name-sym 'id)
|
||||
(= name-sym 'aid)
|
||||
(= name-sym 'trans)
|
||||
@@ -130,7 +130,7 @@ This system grew out of the Crash 2 entity resource system.
|
||||
;; these are the outputs of the function.
|
||||
(let ((hi-tag-idx-out -1)
|
||||
(lo-tag-idx-out -1))
|
||||
;; this value is the index of the most recently passed tag with an "invalid" timestamp
|
||||
;; track invalid timestamp point so we avoid using it in interpolation
|
||||
(let ((most-recent-invalid-time-idx -1)
|
||||
;; read 8 chars of the name we want
|
||||
(type-chars (-> (the-as (pointer uint64) (-> (symbol->string name-sym) data)) 0)))
|
||||
@@ -139,7 +139,6 @@ This system grew out of the Crash 2 entity resource system.
|
||||
;; min/max are inclusive.
|
||||
(let ((max-search (+ (-> this length) -1))
|
||||
(min-search 0))
|
||||
;; inclusive, so >= is correct
|
||||
(while (>= max-search min-search)
|
||||
;; check in the middle of the range to bisect it.
|
||||
(let* ((check-idx (+ min-search (/ (- max-search min-search) 2)))
|
||||
@@ -156,6 +155,7 @@ This system grew out of the Crash 2 entity resource system.
|
||||
;; got to the end of the loop without finding the answer. Set a negative tag
|
||||
(set! tag-idx -1)
|
||||
(label cfg-32)
|
||||
;; return error if the binary search failed.
|
||||
(if (< tag-idx 0) (return (the res-tag-pair tag-idx)))
|
||||
;; if there are multiple tags with the same name and different timesteps, we can't be sure which we ended on.
|
||||
;; this loop brings us to the first tag with the correct name.
|
||||
@@ -219,22 +219,20 @@ This system grew out of the Crash 2 entity resource system.
|
||||
|
||||
(defmethod make-property-data ((this res-lump) (time float) (tag-pair res-tag-pair) (buf pointer))
|
||||
"Return the property data selected by tag-pair at time.
|
||||
Reference properties, exact samples, pairs with different element counts or types, a
|
||||
false buf, and unsupported element types return the lower sample's address directly.
|
||||
Otherwise interpolate every element of matching inline float, integer, or vector arrays
|
||||
into buf and return buf. The caller must provide enough storage for the complete array."
|
||||
This handles interpolation of the data."
|
||||
(let* ((tag-lo (-> this tag (-> tag-pair lo)))
|
||||
(tag-hi (-> this tag (-> tag-pair hi)))
|
||||
(elt-count (-> tag-lo elt-count)))
|
||||
(cond
|
||||
;; references just return the referenced data directly
|
||||
((res-ref? tag-lo) (get-tag-data this tag-lo))
|
||||
((or (not buf)
|
||||
(= (-> tag-pair lo) (-> tag-pair hi))
|
||||
(!= elt-count (-> tag-hi elt-count))
|
||||
(!= (-> tag-lo elt-type) (-> tag-hi elt-type)))
|
||||
((or (not buf) ;; no storage provided
|
||||
(= (-> tag-pair lo) (-> tag-pair hi)) ;; no interp needed
|
||||
(!= elt-count (-> tag-hi elt-count)) ;; different length samples: interpolation impossible
|
||||
(!= (-> tag-lo elt-type) (-> tag-hi elt-type))) ;; differing types
|
||||
(get-tag-data this tag-lo))
|
||||
(else
|
||||
;; A bracketing pair has distinct key frames; exact samples take the path above.
|
||||
;; Interpolation is needed here.
|
||||
(let ((interp (/ (- time (-> tag-lo key-frame)) (- (-> tag-hi key-frame) (-> tag-lo key-frame))))
|
||||
(src-lo (get-tag-data this tag-lo))
|
||||
(src-hi (get-tag-data this tag-hi)))
|
||||
@@ -243,6 +241,7 @@ This system grew out of the Crash 2 entity resource system.
|
||||
(dotimes (i elt-count)
|
||||
(set! (deref float buf i) (+ (* (deref float src-lo i) (- 1.0 interp)) (* (deref float src-hi i) interp))))
|
||||
buf)
|
||||
;; integer interpolation uses 12-bit fractional fixed point
|
||||
(('integer 'sinteger 'uinteger 'int64 'uint64) (make-res-int-data interp elt-count buf src-lo src-hi uint64))
|
||||
(('int8) (make-res-int-data interp elt-count buf src-lo src-hi int8))
|
||||
(('uint8) (make-res-int-data interp elt-count buf src-lo src-hi uint8))
|
||||
@@ -304,10 +303,9 @@ This system grew out of the Crash 2 entity resource system.
|
||||
lookup or type conversion fails.
|
||||
mode controls lookup: base ignores time and selects the first sample, exact requires a
|
||||
sample at time, and interp selects an exact sample or brackets time for interpolation.
|
||||
Integer values are sign- or zero-extended according to their element type; float bits
|
||||
are returned in the same 128-bit container. If tag-addr is nonfalse, write the selected
|
||||
lower res-tag there. buf-addr must hold the interpolated array when interpolation is
|
||||
required."
|
||||
Integer values are sign- or zero-extended according to their element type.
|
||||
If tag-addr is nonfalse, write the selected lower res-tag there. buf-addr must hold
|
||||
the interpolated array when interpolation is required."
|
||||
(let ((tag-pair (lookup-tag-idx this name mode time)))
|
||||
(cond
|
||||
((< (the-as int tag-pair) 0))
|
||||
@@ -511,6 +509,7 @@ This system grew out of the Crash 2 entity resource system.
|
||||
;; get the name and ID
|
||||
(let ((mem-use-id (mem-usage-id res))
|
||||
(mem-use-name "res"))
|
||||
;; the caller may set flags giving us a more specific category
|
||||
(cond
|
||||
((logtest? flags (mem-usage-flags resource-camera)) (set! mem-use-id (mem-usage-id camera)) (set! mem-use-name "camera"))
|
||||
((logtest? flags (mem-usage-flags resource-entity)) (set! mem-use-id (mem-usage-id entity)) (set! mem-use-name "entity"))
|
||||
@@ -570,9 +569,6 @@ This system grew out of the Crash 2 entity resource system.
|
||||
|
||||
(define *res-static-buf* (malloc 'global 128))
|
||||
|
||||
;; Four lookup families cover packed data arrays, referenced structures, raw
|
||||
;; values up to 128 bits, and numeric values converted to float.
|
||||
|
||||
(defmacro res-lump-data (lump name type &key (tag-ptr (the-as (pointer res-tag) #f)) &key (time -1000000000.0))
|
||||
"Return named packed data, interpolating at time when the property has timed samples."
|
||||
`(the-as ,type
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "engine/entity/res.gc")
|
||||
(require "engine/game/game-h.gc")
|
||||
|
||||
;; effect-control interprets animation data and triggers effects.
|
||||
;; This allows artists to script behaviors like footprint markers, walking sound effects, etc
|
||||
;; and have them line up with the animation.
|
||||
|
||||
(define-extern effect-param->sound-spec (function sound-spec (pointer float) int sound-spec))
|
||||
|
||||
(defenum effect-control-flag
|
||||
@@ -20,7 +25,7 @@
|
||||
(last-frame-num float)
|
||||
(channel-offset int32) ;; Root animation channel to follow.
|
||||
(res res-lump) ;; Resource data for the current animation group.
|
||||
(name (pointer res-tag)) ;; First effect-name tag in res.
|
||||
(name (pointer res-tag))
|
||||
(param uint32))
|
||||
(:methods
|
||||
(new (symbol type process-drawable) _type_)
|
||||
|
||||
@@ -72,7 +72,6 @@
|
||||
(fop4 4) ;; unused (no reads or writes)
|
||||
;; if set in an actor's options, a nav-enemy (babak checks it in
|
||||
;; go-initial-state!) spawns dormant in nav-enemy-wait-for-cue instead of idle;
|
||||
;; nothing in shipped actor data sets it.
|
||||
(start-wait-for-cue 5)
|
||||
(instant-collect 6) ;; set on balloon lurker, puffer
|
||||
(skip-jump-anim 7) ;; skips fuel cell "jump" animation
|
||||
@@ -181,8 +180,7 @@
|
||||
this))
|
||||
|
||||
(defmethod pickup-collectable! ((this fact-info) (kind pickup-type) (amount float) (source-handle handle))
|
||||
"Return zero without changing the pickup state; fact-info-target overrides this
|
||||
hook to apply pickups."
|
||||
"Subclasses will override this with a handler for picking up a collectable."
|
||||
0.0)
|
||||
|
||||
(defmethod new fact-info-enemy ((allocation symbol) (type-to-make type) (owner process-drawable) (kind pickup-type) (amount float))
|
||||
|
||||
@@ -2,24 +2,16 @@
|
||||
(in-package goal)
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "kernel-defs.gc")
|
||||
|
||||
(declare-type target process-drawable)
|
||||
|
||||
(declare-type voicebox process-drawable)
|
||||
|
||||
(defun-extern voicebox-spawn process vector (pointer process))
|
||||
|
||||
(declare-type nav-control basic)
|
||||
|
||||
(declare-type path-control basic)
|
||||
|
||||
(declare-type vol-control basic)
|
||||
|
||||
(declare-type actor-link-info basic)
|
||||
|
||||
(declare-type sparticle-launch-control basic)
|
||||
|
||||
(declare-type water-control basic)
|
||||
|
||||
(declare-type collide-shape basic)
|
||||
|
||||
(defenum attack-mask
|
||||
@@ -40,7 +32,7 @@
|
||||
(rotate-to)
|
||||
(prev-state))
|
||||
|
||||
;; Most state flags describe *target* and are queried through that global.
|
||||
;; Most state flags are specific to target.
|
||||
;; Pickups also use fade-out-particles, and basebutton temporarily uses
|
||||
;; use-alt-cam-pos while controlling the camera.
|
||||
(defenum state-flags
|
||||
@@ -70,8 +62,6 @@
|
||||
)
|
||||
|
||||
(defmacro static-attack-info (&key (mask ()) args)
|
||||
;; Derive mask bits from the supplied fields, then initialize a static packet.
|
||||
;; Inline vectors must be copied instead of assigned as references.
|
||||
(let ((mask-actual mask))
|
||||
(dolist (it args)
|
||||
(when (not (member (caar it) mask-actual))
|
||||
@@ -89,6 +79,8 @@
|
||||
;; collision, pickups, particles, water, and sound.
|
||||
(deftype process-drawable (process)
|
||||
;; World pose and, for collidable subclasses, collision geometry.
|
||||
;; many process-drawable types will place a more specific type here
|
||||
;; which includes collision.
|
||||
((root trsqv)
|
||||
;; Joint and bone hierarchy, including the joint-to-bone mappings.
|
||||
(node-list cspace-array)
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
(in-package goal)
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "engine/game/game-h.gc")
|
||||
|
||||
;; Projectile is a base class for weapon or effect "projectiles"
|
||||
;; They typically track a target and play effects or trigger events on collision.
|
||||
|
||||
(declare-type projectile process-drawable)
|
||||
|
||||
(define-extern projectile-init-by-other
|
||||
"Initialize the projectile from source-entity, launch-position, initial-velocity, launch-context
|
||||
option bits, and an optional last-target-handle. Create subtype collision and effects, seed the
|
||||
sixteen-sample stall history, snapshot the parent transform, check initial overlaps for non-blue
|
||||
projectiles, install the moving event hook, and enter the launch state."
|
||||
(function entity-actor vector vector uint handle none :behavior projectile))
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; Frame-local queues filled by drawable-tree draw methods and consumed by finish-background. Each
|
||||
;; terrain category retains the tree together with its owning level so visibility, mood, texture
|
||||
;; buckets, and scratchpad state can be changed between entries. tie-generic carries the per-tree
|
||||
;; continuation for the generic TIE pass, and wait-to-vu0 records background VU0 upload stalls.
|
||||
;; List of things to draw on the current frame.
|
||||
;; Calling "draw" on a background drawable tree simply adds it to this background-work
|
||||
;; The normal tie DMA builder create a chain of instances in tie-generic that is
|
||||
;; later expanded into the generic format in a later pass.
|
||||
(deftype background-work (basic)
|
||||
((tfrag-tree-count int32)
|
||||
(tfrag-trees drawable-tree-tfrag 8)
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
(require "engine/level/bsp-h.gc")
|
||||
(require "engine/util/types-h.gc")
|
||||
|
||||
;; This file is a wild mess of different rendering types.
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; Terrain LOD distance configuration. Profiles 0 through 2 belong to loaded levels; profile 3 is
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "kernel-defs.gc")
|
||||
|
||||
;; Depth-cue is an effect that tries to blur things in the distance,
|
||||
;; however it does not look very good on modern high resolution displays.
|
||||
;; Naughty Dog dropped this effect in later games.
|
||||
;; This is disabled by default on PC.
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; Parameters for one framebuffer depth-cue pass.
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
(require "engine/gfx/foreground/bones-h.gc")
|
||||
(require "engine/geometry/geometry.gc")
|
||||
(require "engine/math/vector.gc")
|
||||
|
||||
(defun light-slerp ((out light) (a light) (b light) (alpha float))
|
||||
"Blend light a toward b into out, clamping alpha to 0 through 1.
|
||||
Color and level are interpolated linearly; direction uses spherical interpolation and
|
||||
preserves a's direction magnitude."
|
||||
Color and level are interpolated linearly; direction uses spherical interpolation."
|
||||
(let ((clamped-alpha (fmax 0.0 (fmin 1.0 alpha))))
|
||||
(vector-lerp! (-> out color) (-> a color) (-> b color) clamped-alpha)
|
||||
(vector-deg-slerp (-> out direction) (-> a direction) (-> b direction) clamped-alpha)
|
||||
@@ -19,15 +19,14 @@
|
||||
|
||||
(defun light-group-slerp ((out light-group) (a light-group) (b light-group) (alpha float))
|
||||
"Blend all three directional lights and the ambient light from
|
||||
group a toward group b into out. light-slerp clamps alpha separately for each light."
|
||||
group a toward group b into out."
|
||||
(dotimes (i 4)
|
||||
(light-slerp (-> out lights i) (-> a lights i) (-> b lights i) alpha))
|
||||
out)
|
||||
|
||||
(defun light-group-process! ((lights vu-lights) (group light-group) (vector-a vector) (vector-b vector))
|
||||
"Convert group into the transposed VU lighting layout in lights.
|
||||
The signed y rotation from vector-b to vector-a is calculated first, but its result is not
|
||||
used."
|
||||
Unused"
|
||||
(rotate-y<-vector+vector vector-b vector-a)
|
||||
(vu-lights<-light-group! lights group)
|
||||
(none))
|
||||
|
||||
@@ -8,17 +8,23 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; Shrubbery is an instanced renderer optimized for little grass, flowers, rocks, etc.
|
||||
;; Shrubs fade out or fade into simple single-quad billboard (always face camera)
|
||||
;; Each instance only has a single color multiplier from the precomputed lighting.
|
||||
;; (it still uses time of day interpolation, so a shrub can still flicker by a torch,
|
||||
;; but all vertices receive the same final interpolated time-of-day color)
|
||||
;; Shrubs don't have precomputed visibility, but still do frustum culling.
|
||||
|
||||
;; The coarsest geometry a shrub prototype can have: one camera-facing quad with one texture. There
|
||||
;; is no vertex data -- the EE builds the four corners from the instance's own flat-normal and
|
||||
;; flat-hwidth and writes them straight to the GS -- so the shader is the whole object.
|
||||
(deftype billboard (drawable)
|
||||
((flat adgif-shader :inline)))
|
||||
|
||||
;; The three quadwords of camera constants uploaded to VU address zero once per pass. The overlays
|
||||
;; are not alternative readings of the same value; they are what different parts of the system call
|
||||
;; the same word. tex-start-ptr and mtx-buf-ptr are initial values for two words the microprogram
|
||||
;; reuses as its own saved cursors, and exp23 names the 2^23 bias that lets VU addresses travel in
|
||||
;; float lanes.
|
||||
;; The three quadwords of camera constants uploaded to VU data address 0.
|
||||
;; tex-start-ptr and mtx-buf-ptr are initial values for two words the microprogram
|
||||
;; reuses as its own saved cursors, and exp23 names the 2^23 bias that lets VU do address
|
||||
;; math in float registers.
|
||||
(deftype shrub-view-data (structure)
|
||||
((data uint128 3)
|
||||
(texture-giftag gs-gif-tag :inline :overlay-at (-> data 0))
|
||||
@@ -58,6 +64,10 @@
|
||||
(flat-hwidth float :overlay-at (-> flat-normal w))
|
||||
(color uint32 :overlay-at color-indices)))
|
||||
|
||||
;; drawable system types for shrubs, allowing BVH traversal for frustum culling.
|
||||
;; unlike other BVHs, shrub doesn't have fixed depth and 8-child counts.
|
||||
;; The usual optimized draw-node asm therefore doesn't work.
|
||||
;; (shrub instead traverses the BVH in DFS order at DMA generation time using a stack)
|
||||
(deftype drawable-inline-array-instance-shrub (drawable-inline-array)
|
||||
((data instance-shrubbery 1 :inline)
|
||||
(pad uint32)))
|
||||
@@ -66,6 +76,7 @@
|
||||
((info prototype-array-shrub-info :offset 8)
|
||||
(colors-added time-of-day-palette :offset 12)))
|
||||
|
||||
;; duplicate geometry for the generic renderer - used when shrubs need clipping.
|
||||
(deftype generic-shrub-fragment (drawable)
|
||||
((textures (inline-array adgif-shader) :overlay-at id)
|
||||
(vtx-cnt uint32 :offset 8)
|
||||
@@ -86,19 +97,16 @@
|
||||
|
||||
(deftype prototype-generic-shrub (drawable-group) ())
|
||||
|
||||
;; One instance as VU1 sees it: five quadwords unpacked into an instance ring slot. The ring's count
|
||||
;; word sits one quadword before the first of these, which is why the microprogram's record stride is
|
||||
;; six on entry and five thereafter.
|
||||
;; Shrub matrix and color uploaded to VU1 per instance.
|
||||
(deftype shrubbery-matrix (structure)
|
||||
((mat matrix :inline)
|
||||
(color qword :inline)))
|
||||
|
||||
(defun shrubbery-login-post-texture ((this shrubbery))
|
||||
"Repack the logged-in adgif shaders into the shrub's VU1-facing DMA data. Each shader pair keeps
|
||||
two texture-register qwords but shares one four-qword state block; the first state qword updates
|
||||
only its three register words and preserves the packet word already in the destination."
|
||||
"Repack the logged-in adgif shaders into the shrub's VU1-facing DMA data.
|
||||
Each shader pair shares data and is repacked for more efficient uploads."
|
||||
;; Each source adgif is five qwords. The pair has different texture registers but identical
|
||||
;; remaining state, so the VU1 packet stores both first qwords and only the first shader's state.
|
||||
;; remaining state, so the VU1 packet doesn't store the identical part twice.
|
||||
(let* ((shader-pair-count (-> this header data 0))
|
||||
(state-dst (the-as qword (+ (the-as uint (-> this header)) (* (+ (-> this header data 1) 1) 16))))
|
||||
(texture-dst (the-as qword (+ (the-as int state-dst) (* shader-pair-count 64))))
|
||||
@@ -127,45 +135,34 @@
|
||||
;; Shrub VU1 addresses
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; The three quadwords of camera constants land at VU address zero and shrub-view-data describes
|
||||
;; them, so the program's loads name fields instead of numbers. Integer division of a field offset
|
||||
;; by sixteen also lets a lane-level field name the quadword that holds it, which is how
|
||||
;; tex-start-ptr and mtx-buf-ptr identify the two words the program later reuses as saved cursors.
|
||||
;; models, instances, and output data are all double-buffered.
|
||||
;; (unlike tie, shrub doesn't triple buffer the outputs)
|
||||
|
||||
(defconstant SHRUB-VU-VIEW-DATA 0)
|
||||
|
||||
(defmacro shrub-view-const (&rest path)
|
||||
`(+ SHRUB-VU-VIEW-DATA (/ (offset-of shrub-view-data ,@path) 16)))
|
||||
|
||||
;; The two model banks. *shrub-state* is the VIF BASE register for the next model upload and
|
||||
;; alternates between them; subtracting it from the sum is how both the EE and the microprogram
|
||||
;; flip. Each bank is 160 quadwords, which is the largest shrubbery the exporter will emit.
|
||||
;; alternates between them. Each bank is 160 quadwords
|
||||
(defconstant SHRUB-VU-MODEL-BANK-A 2)
|
||||
|
||||
(defconstant SHRUB-VU-MODEL-BANK-B 162)
|
||||
|
||||
(defconstant SHRUB-VU-MODEL-BANK-SUM (+ SHRUB-VU-MODEL-BANK-A SHRUB-VU-MODEL-BANK-B))
|
||||
|
||||
;; The two instance rings. A ring is one count word followed by ten shrubbery-matrix records, so the
|
||||
;; second ring's address, the stride the draw entry walks, and the sum it flips through all come out
|
||||
;; of the type. Record k sits at ring + 1 + 5k; the draw entry reads the first record at fixed
|
||||
;; offsets from the count word and then walks the rest with post-incrementing loads.
|
||||
;; The two instance rings. A ring is one count word followed by ten shrubbery-matrix records.
|
||||
(defconstant SHRUB-VU-MATRIX-STRIDE (/ (type-size shrubbery-matrix) 16))
|
||||
|
||||
(defconstant SHRUB-VU-RING-SLOTS 10)
|
||||
|
||||
(defconstant SHRUB-VU-RING-A 322)
|
||||
|
||||
(defconstant SHRUB-VU-RING-B (+ SHRUB-VU-RING-A 1 (* SHRUB-VU-RING-SLOTS SHRUB-VU-MATRIX-STRIDE)))
|
||||
|
||||
(defconstant SHRUB-VU-RING-SUM (+ SHRUB-VU-RING-A SHRUB-VU-RING-B))
|
||||
|
||||
(defmacro shrub-matrix-qword (&rest path)
|
||||
`(+ 1 (/ (offset-of shrubbery-matrix ,@path) 16)))
|
||||
|
||||
;; The two GIF output buffers, which begin where ring B ends. Their contents are a packet described
|
||||
;; by the model's own object stream rather than by any GOAL type, so these stay plain constants.
|
||||
;; The two GIF output buffers, which begin where ring B ends.
|
||||
(defconstant SHRUB-VU-GIF-BUFFER-0 (+ SHRUB-VU-RING-B 1 (* SHRUB-VU-RING-SLOTS SHRUB-VU-MATRIX-STRIDE)))
|
||||
|
||||
(defconstant SHRUB-VU-GIF-BUFFER-1 (+ SHRUB-VU-GIF-BUFFER-0 400))
|
||||
|
||||
;; Entry points. Entry 0 loads the camera constants and builds the buffer-address vectors. Entries
|
||||
@@ -173,11 +170,8 @@
|
||||
;; the following draw will read, and start-bank in shrub-work.gc records which one each ring
|
||||
;; position needs. Entry 103 draws one ring of instances against the prepared model.
|
||||
(defconstant SHRUB-VU-ENTRY-INIT 0)
|
||||
|
||||
(defconstant SHRUB-VU-ENTRY-INIT-MODEL-A 17)
|
||||
|
||||
(defconstant SHRUB-VU-ENTRY-INIT-MODEL-B 21)
|
||||
|
||||
(defconstant SHRUB-VU-ENTRY-DRAW 103)
|
||||
|
||||
;; The VIF BASE register for the next model upload, and so the model bank the next shrubbery lands
|
||||
@@ -186,8 +180,7 @@
|
||||
|
||||
;; The DMA/VIF template for one near-shrub fragment, handed to the generic renderer rather than to
|
||||
;; shrub's own VU1 program. Six of the seven packets are patched per fragment -- qwc, source address
|
||||
;; and unpack count -- and the seventh runs the generic entry. Six of these exist so the EE can
|
||||
;; rotate to a free one while an earlier chain still names the last.
|
||||
;; and unpack count -- and the seventh runs the generic entry.
|
||||
(deftype shrub-near-packet (structure)
|
||||
((matrix-tmpl dma-packet :inline)
|
||||
(header-tmpl dma-packet :inline)
|
||||
@@ -202,14 +195,10 @@
|
||||
;;
|
||||
;; * templates the EE copies and patches: the twenty matrix and count packets of the instance ring,
|
||||
;; the two MSCALF packets, the adgif and billboard GIF packets, and the six near packets.
|
||||
;; * per-frame values shared with VU0: the camera planes and guard planes, the hvdf offset, the
|
||||
;; * per-frame values: the camera planes and guard planes, the hvdf offset, the
|
||||
;; min-dist accumulator, and colors -- the level's 1024-entry time-of-day palette.
|
||||
;; * the builder's own state: the six-deep node stack, the two 128-byte node chain staging areas,
|
||||
;; the current bucket's four list heads, the scratchpad cursors and the DMA stall counters.
|
||||
;;
|
||||
;; dummy exists to give the 64-byte alignment of the two chain buffers somewhere to land: the builder
|
||||
;; rounds work+chaina and work+chainb down to a cache line, and without the padding in front the
|
||||
;; first would round below the start of the type.
|
||||
(deftype instance-shrub-work (structure)
|
||||
((dummy qword 3 :inline)
|
||||
(chaina qword 8 :inline)
|
||||
@@ -272,11 +261,6 @@
|
||||
(wait-from-spr uint32)
|
||||
(wait-to-spr uint32)))
|
||||
|
||||
;; The scratchpad, overlaid on the work area of the terrain-context so the level header at the bottom
|
||||
;; of the scratchpad survives. Two input banks of 325 quadwords each hold instance records copied in
|
||||
;; by the toSPR channel, and two output banks of 128 quadwords each hold packets on their way back to
|
||||
;; the DMA buffer. All four addresses carry the work-area bias, which is why the flip masks are not
|
||||
;; simply the bank spacing.
|
||||
(deftype instance-shrub-dma (structure)
|
||||
((instancea uint128 325)
|
||||
(instanceb uint128 325)
|
||||
|
||||
@@ -6,71 +6,47 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; Per-patch triangle and display-vertex counts, one entry per detail level plus a spare, filled in by
|
||||
;; the exporter and read only by stats-tfrag-asm for the terrain debug display. dverts counts the
|
||||
;; vertices a strip actually sends, which is two more than its triangle count per strip - which is how
|
||||
;; the debug display recovers the average strip length from the pair.
|
||||
;; Per-patch triangle and vertex counts, one entry per detail level plus a spare
|
||||
;; dverts counts the vertices a strip actually sends, two more than triangle count.
|
||||
(deftype tfragment-stats (structure)
|
||||
((num-tris uint16 4)
|
||||
(num-dverts uint16 4)))
|
||||
|
||||
;; Debug-only, and absent from the retail levels: debug-lines is a null pointer there. edge-debug-lines
|
||||
;; draws the lists when they exist.
|
||||
;; Debug-only, and absent from the retail levels.
|
||||
(deftype tfragment-debug-data (structure)
|
||||
((stats tfragment-stats :inline)
|
||||
(debug-lines (array vector-array))))
|
||||
|
||||
;; Declared, never built out. tfragment has no GENERIC path at all: nothing in the game reads or
|
||||
;; writes generic-tfragment or tfragment.generic, there is no environment-mapped or software-transformed
|
||||
;; terrain, and dummy exists only so the type has a size. Terrain always goes through VU1.
|
||||
;; Unused. Tfrag never falls back to generic.
|
||||
(deftype generic-tfragment (structure)
|
||||
((dummy int32)))
|
||||
|
||||
;; One independently culled terrain patch, and one of three nested meshes over the same vertices.
|
||||
;; A tfragment is one independently culled terrain patch, with three levels of detail.
|
||||
;;
|
||||
;; The geometry is a single contiguous block of VIF commands in the level file, and the four transfers
|
||||
;; The geometry is a single contiguous block of data in the level file, and the four transfers
|
||||
;; below are four windows into it. Nothing is duplicated except the per-level draw-point and strip
|
||||
;; tables, because those are the only part that a change of detail actually changes. Measured across
|
||||
;; JUN, BEA, VI1 and SNO, the block is laid out relative to dma-common (in quadwords):
|
||||
;; tables. The block is laid out:
|
||||
;; BASE-ONLY
|
||||
;; base-only mesh tables
|
||||
;; COMMON
|
||||
;; control block, shaders, base point records, base vertices
|
||||
;; LEVEL-0
|
||||
;; level-0-only mesh tables
|
||||
;; level-0 interp table, point records, vertices
|
||||
;; LEVEL-1
|
||||
;; level-1-only mesh tables
|
||||
;; level-1 vertices, point records.
|
||||
;;
|
||||
;; -8 .. 0 base-only draw-point and strip tables dma-base points here
|
||||
;; 0 .. C control block, adgif shaders, base point records, base vertices ("common")
|
||||
;; C .. L level-0-only draw-point and strip tables
|
||||
;; L .. Z level-0 additions: interpolation table, point records, vertices dma-level-1 here
|
||||
;; Z .. E level-1 additions: vertices, point records, and its own tables
|
||||
;; Therefore to draw each level:
|
||||
;;
|
||||
;; and the four transfers are
|
||||
;; Base: single upload. Start at dma-base (BASE-ONLY), upload dma-qwc[1] (upload BASE-ONLY, COMMON)
|
||||
;; Level0: single upload, Start at dma-level0 (overlays dma-common), upload dma-qwc[2] (upload COMMON, LEVEL-0)
|
||||
;; Level1: two uploads,
|
||||
;; dma-common, dma-qwc[0], only loads COMMON
|
||||
;; dma-level-1, dmq-qwc[3], loads LEVEL-1
|
||||
;;
|
||||
;; base dma-base for dma-qwc[1] -> base tables, then everything in "common"
|
||||
;; common dma-common for dma-qwc[0] -> "common" alone; dma-qwc[0] = C
|
||||
;; level 0 dma-level-0 for dma-qwc[3] -> "common", level-0 tables, level-0 additions;
|
||||
;; dma-qwc[3] = Z
|
||||
;; level 1 dma-level-1 for dma-qwc[2] -> level-0 additions, then level-1 additions;
|
||||
;; dma-qwc[2] = E - L
|
||||
;;
|
||||
;; So a base draw is one transfer, a level-0 draw is one transfer, and a level-1 draw is two: "common"
|
||||
;; followed by the level-1 window, which deliberately skips the level-0-only tables in between while
|
||||
;; still picking up the level-0 additions that level 1 also needs. dma-common and dma-level-0 are one
|
||||
;; field under two names because the level-0 window simply starts where "common" starts; the two names
|
||||
;; distinguish "send the common prefix" from "send the whole level-0 window". That is also why
|
||||
;; dma-chain has three entries and dma-qwc has four - three distinct start addresses, four lengths.
|
||||
;;
|
||||
;; dma-qwc is in chain-entry order with the odd one appended, not in level order:
|
||||
;; dma-qwc[0] length of the common prefix (with dma-chain[0])
|
||||
;; dma-qwc[1] length of the base window (with dma-chain[1])
|
||||
;; dma-qwc[2] length of the level-1 window (with dma-chain[2])
|
||||
;; dma-qwc[3] length of the whole level-0 window (with dma-chain[0] again)
|
||||
;;
|
||||
;; Because the windows overlap, never treat the three pointers as three independent allocations; that
|
||||
;; is what mem-usage is subtracting for. A patch with no level-1 detail leaves dma-level-1 aliased onto
|
||||
;; dma-chain[0] and unused; num-level1-colors zero is the test for that, and likewise
|
||||
;; num-level0-colors zero means there is no level-0 window either.
|
||||
;;
|
||||
;; Every window unpacks the same five-quadword tfrag-control to the front of the VU input bank, and all
|
||||
;; three levels write their draw-point and strip tables at the same VU addresses, so the control block
|
||||
;; never has to change with the detail level.
|
||||
;;
|
||||
;; Colors are the one part of a patch that is not in the level file's VIF block, because they follow
|
||||
;; Colors are the one part of a patch that is not in the level file's data block, because they follow
|
||||
;; the time of day. One time-of-day-palette is shared by the whole tree (drawable-tree-tfrag has it),
|
||||
;; and each patch carries its own indices into that palette here:
|
||||
;;
|
||||
@@ -80,12 +56,6 @@
|
||||
;; num-level1-colors number of vertices in base + level 0 + level 1
|
||||
;; color-offset the VU quadword where the expanded colors start
|
||||
;;
|
||||
;; The counts are cumulative over the nested vertex array, which is exactly what the EE needs: having
|
||||
;; chosen a stream it takes the matching count, expands that many indices into scratchpad RGBA, and
|
||||
;; writes the count into the color template's VIF NUM byte - num-base-colors for a base draw,
|
||||
;; num-level0-colors for level 0, num-level1-colors for level 1. So one number selects both how much
|
||||
;; color to gather and how much to unpack. color-offset is odd because vertex positions unpack on a
|
||||
;; 2/1 VIF cycle and the colors land in the quadwords the positions skip, one color per position.
|
||||
(deftype tfragment (drawable)
|
||||
((color-index uint16 :offset 6)
|
||||
(debug-data tfragment-debug-data :offset 8)
|
||||
@@ -112,46 +82,32 @@
|
||||
(generic generic-tfragment)
|
||||
(generic-u32 uint32 :overlay-at generic)))
|
||||
|
||||
;; The patch list. data is dynamic despite the declared length of one; the real count is the inherited
|
||||
;; length field, and the fragments are one contiguous 64-byte-stride run, which is what lets the EE draw
|
||||
;; functions walk them with a fixed stride and DMA sixteen headers at a time. Retail levels have one such
|
||||
;; array per terrain tree, of up to a couple of thousand fragments.
|
||||
;; Array of tfragments in the drawable BVH system.
|
||||
;; These use the usual fixed-max-depth, always 8 children layout and can be culled
|
||||
;; via precomputed visibility and BVH frustum culling very efficiently in draw-node.
|
||||
(deftype drawable-inline-array-tfrag (drawable-inline-array)
|
||||
((data tfragment 1 :inline)
|
||||
(pad uint32)))
|
||||
|
||||
;; The translucent variant declares a second dynamic slot at offset 112. It is not a separate list: the
|
||||
;; declaration exists because the type is one tfragment longer than its parent, and the drawing code
|
||||
;; treats it exactly like the ordinary array.
|
||||
;; Variant for "transparent" tfrags, this is likely a mistake and unused.
|
||||
;; It has a second tfragment defined, but nothing seems to read it.
|
||||
(deftype drawable-inline-array-trans-tfrag (drawable-inline-array-tfrag)
|
||||
((data2 tfragment 1 :inline)
|
||||
(pad2 uint32)))
|
||||
|
||||
;; One terrain tree. arrays is every depth of the visibility hierarchy: each array before the last is a
|
||||
;; level of draw-node, and the last is the drawable-inline-array-tfrag holding the patches. Culling walks
|
||||
;; the depths, propagating visibility down, and the leaf array is then handed to the draw functions.
|
||||
;;
|
||||
;; The time-of-day palette is per tree, not per patch: every fragment's color-indices index into this one
|
||||
;; palette, and finish-background interpolates it once per frame per tree. That is why the trees are split
|
||||
;; by surface type in the first place - one palette and one set of GS state per tree.
|
||||
;; Full drawable tree (BVH hierarchy) for tfrag.
|
||||
;; Each array is at increasing depth in the BVH. The final array contains
|
||||
;; tfragment and the others contain draw-nodes (bounding sphere nodes)
|
||||
;; There's a single color palette shared for the entire tree.
|
||||
(deftype drawable-tree-tfrag (drawable-tree)
|
||||
((time-of-day-pal time-of-day-palette :offset 12)
|
||||
(arrays drawable-inline-array 1 :overlay-at (-> data 0))))
|
||||
|
||||
;; The five subtypes below differ only in which bucket and which GS TEST setting they draw with; the
|
||||
;; geometry, the LOD machinery and the microprograms are identical. tfrag-methods.gc has the alpha tests:
|
||||
;; opaque terrain uses alpha >= #x26, translucent >= #x7e with framebuffer-only alpha failure, dirt uses
|
||||
;; framebuffer-only failure with no alpha comparison, and ice always passes alpha with the same failure
|
||||
;; mode. The lowres variants are declared for a distant-terrain pass; no consumer distinguishes them from
|
||||
;; their parents, and whether any shipped level actually builds one was not established here.
|
||||
;; The five subtypes below differ only in which bucket and which GS TEST setting they draw with
|
||||
(deftype drawable-tree-trans-tfrag (drawable-tree-tfrag) ())
|
||||
|
||||
(deftype drawable-tree-dirt-tfrag (drawable-tree-tfrag) ())
|
||||
|
||||
(deftype drawable-tree-ice-tfrag (drawable-tree-tfrag) ())
|
||||
|
||||
(deftype drawable-tree-lowres-tfrag (drawable-tree-tfrag) ())
|
||||
|
||||
(deftype drawable-tree-lowres-trans-tfrag (drawable-tree-trans-tfrag) ())
|
||||
|
||||
;; The LOD collapse coefficients, one entry per subdivision level. Despite looking like four
|
||||
@@ -193,8 +149,8 @@
|
||||
(k0s uint128 2 :overlay-at (-> data 40))
|
||||
(k1s uint128 2 :overlay-at (-> data 48))))
|
||||
|
||||
;; The five quadwords at the front of every VU1 terrain input bank. Every pointer is a quadword
|
||||
;; address relative to the bank base, so it can be added straight to the VIF TOP register.
|
||||
;; Tfrag data layout. `ptr`s are quadword addresses.
|
||||
;; TODO: this is very hard to understand - rewrite once we get to tfrag.gc
|
||||
;;
|
||||
;; A vertex is two quadwords: packed integer position, then the time-of-day color the EE unpacks into
|
||||
;; the quadword the position skipped. Positions live at ptr-vtxdata in base, level-0, level-1 order,
|
||||
@@ -244,10 +200,6 @@
|
||||
(ptr-strip-data uint32)
|
||||
(ptr-texture-data uint32)))
|
||||
|
||||
;; Counters for the tfrag-print-stats debug page, filled in by hand from the shipped level data rather
|
||||
;; than by the renderer - nothing in the drawing path writes them, and the single instance is the global
|
||||
;; t-stat in tfrag.gc. The page turns them into an estimated DMA cost per frame, which is what the from,
|
||||
;; to and cnt fields are for.
|
||||
(deftype tfrag-stats (structure)
|
||||
((from int32)
|
||||
(to int32)
|
||||
@@ -266,8 +218,7 @@
|
||||
(drawpoints int32)
|
||||
(vif int32)))
|
||||
|
||||
;; Two quadwords of DMA/VIF tag. Declared here and referenced by nothing: the EE draw functions build
|
||||
;; their packets straight out of the tfrag-work templates instead.
|
||||
;; Seems unused.
|
||||
(deftype tfrag-packet (structure)
|
||||
((tag uint128 2)))
|
||||
|
||||
@@ -305,7 +256,7 @@
|
||||
|
||||
;; Scratchpad terrain workspace. banka and bankb each hold one batch of sixteen fragment headers, so
|
||||
;; the toSPR DMA can be filling one while packets are built from the other; outa and outb each hold
|
||||
;; 128 quadwords of built packet, so the fromSPR DMA can be feeding the VIF buffer from one while the
|
||||
;; 128 quadwords of built packet, so the fromSPR DMA can be writing back to main memory from one while the
|
||||
;; other is written. colors is where the EE gathers this frame's time-of-day RGBA before handing it to
|
||||
;; the VU as part of each fragment's packet.
|
||||
(deftype tfrag-dma (structure)
|
||||
|
||||
@@ -5,26 +5,19 @@
|
||||
(require "engine/draw/drawable-tree-h.gc")
|
||||
(require "engine/draw/drawable-inline-array-h.gc")
|
||||
|
||||
;; TIE's data types. Three separate things live in here and it helps to keep them apart:
|
||||
;; TIE types for:
|
||||
;;
|
||||
;; * the prototype side -- prototype-tie and tie-fragment -- geometry authored once and uploaded to
|
||||
;; VU1 once per frame;
|
||||
;; * the instance side -- instance-tie and its drawable arrays -- the BVH of placements;
|
||||
;; * the two scratchpad work areas the EE packet builders run out of.
|
||||
;; * the prototypes -- prototype-tie and tie-fragment -- geometry uploaded to VU1 once per frame;
|
||||
;; * the instances -- instance-tie and its drawable arrays -- the BVH of prototype placements;
|
||||
;; * the two scratchpad work areas for DMA generation on the EE
|
||||
;;
|
||||
;; A fragment holds only counts and references. The actual shaders, points, strip descriptions, and
|
||||
;; colors sit in separate blocks of level data that nothing in GOAL ever dereferences: they are DMA
|
||||
;; sources and VU1 input, and the only code that understands their layout is the microprogram in
|
||||
;; tie.gc and the packet builders in tie-methods.gc. A field with no GOAL reference is not therefore
|
||||
;; unused.
|
||||
;; A prototype-tie references geometry fragments which is a chunk of mesh. Mesh size is limited
|
||||
;; by the VU1 data memory size.
|
||||
;;
|
||||
;; Ownership of the color data is split and it is easy to get backwards. The palette -- the colors --
|
||||
;; belongs to the prototype, in prototype-bucket-tie.tie-colors, and is uploaded once per prototype per
|
||||
;; frame for every fragment and every instance to share. What an instance owns is instance-tie's
|
||||
;; color-indices: a stream of one-byte indices into that shared palette, one per vertex. So instances of
|
||||
;; the same prototype are identical in geometry and in available colors, and differ only in which entry
|
||||
;; each of their vertices picks -- which is what lets the same authored crate sit in sunlight and in
|
||||
;; shadow for one byte per vertex.
|
||||
;; Ownership of the color data is split and it is easy to get backwards. The color palette (actual RGBs)
|
||||
;; belong to the prototype. Each instance has its own indices, allowing it to select instance-specific
|
||||
;; colors. (note that there's a single giant palette shared by all prototypes, prototypes just have
|
||||
;; a view into this)
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
@@ -33,24 +26,18 @@
|
||||
;; is either DMA'd straight to VU1 or read by the palette expander; the counts are what the packet
|
||||
;; builder patches into its templates.
|
||||
(deftype tie-fragment (drawable)
|
||||
((gif-ref (inline-array adgif-shader) :overlay-at id) ;; adgif shaders, five quadwords each
|
||||
(point-ref uint32 :offset 8) ;; packed points, uploaded as V4-16 to VU address 50. Nothing in the
|
||||
;; source declares a type for this stream; the closest are
|
||||
;; generic-tie-base-point and generic-tie-interp-point, which are the
|
||||
;; Generic converter's view of its own copy of the geometry.
|
||||
((gif-ref (inline-array adgif-shader) :overlay-at id) ;; adgif shaders
|
||||
(point-ref uint32 :offset 8) ;; packed points, uploaded as V4-16 to VU address 50.
|
||||
(color-index uint16 :offset 12) ;; this fragment's first entry in the prototype color table
|
||||
(base-colors uint8 :offset 14) ;; palette entries used by base points; each interpolated point takes three
|
||||
(tex-count uint16) ;; five times the shader count; login divides it back down
|
||||
(gif-count uint16) ;; quadwords of shader data to upload
|
||||
(vertex-count uint16) ;; quadwords in the point stream
|
||||
(color-count uint16) ;; palette entries this fragment selects from the prototype table
|
||||
(base-colors uint8 :offset 14) ;; unused? unknown meaning.
|
||||
(tex-count uint16) ;; size of adgifs in qw
|
||||
(gif-count uint16) ;; size of giftag templates in qw
|
||||
(vertex-count uint16) ;; size of points in qw
|
||||
(color-count uint16) ;; size of colors used in qw
|
||||
(num-tris uint16) ;; triangles, for the renderer statistics display
|
||||
(num-dverts uint16) ;; output vertex slots in this fragment's GIF packets -- base points and
|
||||
;; interpolated points together, and a vertex shared by two strips counts once
|
||||
;; per strip. collect-stats multiplies it by the instance count to get the
|
||||
;; drawn-vertex total, so "d" is the destination slot each one occupies.
|
||||
(dp-ref uint32) ;; strip descriptions: GIF tag templates and their destination offsets
|
||||
(dp-qwc uint32) ;; quadwords of strip description
|
||||
(num-dverts uint16) ;; output vertex slots in this fragment's GIF packets
|
||||
(dp-ref uint32) ;; unknown metadata for near renderer
|
||||
(dp-qwc uint32) ;; quadwords of dp
|
||||
(generic-ref uint32) ;; generic-tie-header and its compact stream, when this fragment has one
|
||||
(generic-count uint32) ;; quadwords of Generic data
|
||||
(debug-lines (array vector-array)))) ;; authoring-time wireframe, absent from shipped levels
|
||||
@@ -58,10 +45,7 @@
|
||||
;; One placement of a prototype. Instances are the leaves of the TIE tree's BVH, so rejecting a draw
|
||||
;; node discards a whole subtree of them at once.
|
||||
;;
|
||||
;; The transform is a matrix4h: sixteen int16, 32 bytes. Its three rotation rows are 1.12 fixed point
|
||||
;; and its translation row steps in units of 64 world units, which is how a complete placement fits in
|
||||
;; 64 bytes including the bounding sphere. See the unpack at the top of
|
||||
;; draw-inline-array-instance-tie.
|
||||
;; The transform is a matrix4h with fixed-point integer values.
|
||||
(deftype instance-tie (instance)
|
||||
((color-indices uint32 :overlay-at error) ;; per-instance palette indices, or zero to use the prototype's
|
||||
(bucket-ptr prototype-bucket-tie :offset 12) ;; the prototype this places
|
||||
@@ -107,15 +91,10 @@
|
||||
:bitfield #t
|
||||
(has-generic 1))
|
||||
|
||||
;; Everything the instance packet builder needs that is not in the instance itself: camera constants,
|
||||
;; the DMA/VIF templates it patches per instance, cursors into the visibility string, and the stall
|
||||
;; counters. tie-work.gc initializes the fixed part; the draw code fills in the camera and cursor
|
||||
;; fields each frame and copies the whole thing into draw-local storage, since the builder writes to
|
||||
;; it and the shared original must survive.
|
||||
(deftype instance-tie-work (structure)
|
||||
((wind-const vector :inline) ;; wind spring: damping, force scale, timestep, low clamp
|
||||
(hmge-d vector :inline) ;; homogeneous depth range used by the near test
|
||||
(hvdf-offset vector :inline) ;; screen-space offset from the camera
|
||||
(hvdf-offset vector :inline) ;; see math-camera.gc
|
||||
(wind-force vector :inline)
|
||||
(constant vector :inline) ;; 4096.0 and 128.0: the wind phase clamp
|
||||
(far-morph vector :inline) ;; (1, 0, 0, 256): the fully collapsed morph quadword
|
||||
@@ -150,10 +129,6 @@
|
||||
|
||||
;; The instance builder's scratchpad: two input banks of 32 instances, two 4 KiB output banks, and a
|
||||
;; copy of the work area after them.
|
||||
;;
|
||||
;; The whole record sits one quadword into the scratchpad, leaving the first quadword for control
|
||||
;; words. That is why every displacement in the packet builders is a field offset plus sixteen -- see
|
||||
;; spr-offset in tie-methods.gc.
|
||||
(deftype instance-tie-dma (structure)
|
||||
((banka instance-tie 32 :inline) ;; exactly one visibility word's worth of instances
|
||||
(bankb instance-tie 32 :inline)
|
||||
@@ -190,9 +165,7 @@
|
||||
(near-wait-from-spr uint32)
|
||||
(near-wait-to-spr uint32)))
|
||||
|
||||
;; The prototype builder's scratchpad: two 1 KiB palette banks, two 4 KiB output banks, and the
|
||||
;; per-prototype state its fragment loop works from. Like instance-tie-dma, this record starts one
|
||||
;; quadword into the scratchpad.
|
||||
;; The prototype builder's scratchpad
|
||||
(deftype prototype-tie-dma (structure)
|
||||
((colora rgba 256) ;; a 1 KiB source chunk is 32 time-of-day entries; each becomes one word
|
||||
(colorb rgba 256)
|
||||
|
||||
@@ -3,75 +3,146 @@
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "engine/draw/drawable-h.gc")
|
||||
|
||||
;; Every level ends with a large "bt" file containing its bsp-header. Loading it last lets the
|
||||
;; static level data consume the rest of the level heap. The header owns or references the BSP,
|
||||
;; drawable trees, actors, cameras, collision properties, textures, and visibility data; it is much
|
||||
;; broader than its historical name suggests. The shipped files use the -vis suffix because they
|
||||
;; include precomputed visibility data.
|
||||
;; Every level DGO file ends with a large "bt" file containing its bsp-header.
|
||||
;; Loading it last lets it load directly onto the level-heap, skipping the usual double-buffered
|
||||
;; load and link loader for smaller files.
|
||||
;; The bsp-header has references to the actual BSP, drawable trees, actors, cameras, collision properties,
|
||||
;; visibility, and more. The engine stashes references to texture pages and other data here too.
|
||||
;; The final game files use the -vis suffix because they include precomputed visibility data.
|
||||
;;
|
||||
;; "BSP" generally means this static level data, while "level" means its runtime state.
|
||||
|
||||
(declare-type entity-camera basic)
|
||||
|
||||
;; flags: 1 = load
|
||||
;; 2 = display
|
||||
;; Each terminal BSP side stores six of these two-bit pairs, one per neighboring level.
|
||||
;; The actual BSP is very strange.
|
||||
;; The bsp data structure is strongly inspired by a quake-style BSP.
|
||||
;; In this approach, each splitting plane is a face from the level geometry,
|
||||
;; and visibility is precomputed by casting rays through "portals".
|
||||
;; The design here is based on this, and ND developers stated this is how it works
|
||||
;; in a GDC talk.
|
||||
|
||||
;; The actual data doesn't match this description. All bsp-nodes describe regularly sized
|
||||
;; rectangular prisms. (Jak 2 and on use a more comapct data structure: quantized AABBs)
|
||||
;; It's also a suspicious design. Can the portals really work for big outdoor levels?
|
||||
|
||||
;; My guess is that they started with portals, then pivoted to something else.
|
||||
;; This "something else" uses rectangular volumes, which is awfully similar to
|
||||
;; what they did in Jak 2 and on, and _might_ have been the Insomniac approach,
|
||||
;; although this is pure speculation, ND might have done their own visibility precomputation.
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; Each plane splits space into front and back children. Front is
|
||||
;; dot(position, plane.xyz) - plane.w >= 0. A positive child is another bsp-node pointer; a
|
||||
;; nonpositive value identifies a terminal side; visibility trees use negative values to encode
|
||||
;; their leaf indices. Each side also carries the packed load/display pairs used when the camera
|
||||
;; reaches that terminal side.
|
||||
;; splitting planes in a BSP
|
||||
(deftype bsp-node (structure)
|
||||
((front int32)
|
||||
(back int32)
|
||||
;; front/back indices are either:
|
||||
;; - positive value indicating a child bsp-node
|
||||
;; - negative value for a leaf node
|
||||
((front int32) ;; if dot(p, plane.xyz) - >= plane.w
|
||||
(back int32) ;; otherwise
|
||||
|
||||
;; these flags appear to be used for diagnostics only.
|
||||
;; for each 6 neighboring levels, there is a load and display bit
|
||||
;; when the display bit is 0, the visibility generator would
|
||||
;; assume that the neighbor level isn't drawn, and therefore skips
|
||||
;; computation and maps the cell to all 0's.
|
||||
;; these are very similar, but not quite the same as the load boundaries.
|
||||
;; this means that you can have a level in "display", but all geometry is
|
||||
;; hidden because the camera is in a volume with display = 0.
|
||||
;; (it's possible that display/load was once triggered from these!)
|
||||
(front-flags uint32)
|
||||
(back-flags uint32)
|
||||
(plane vector :inline)))
|
||||
|
||||
;; This drawable is stored first in the level bt file; drawing it draws the static level.
|
||||
(deftype bsp-header (drawable)
|
||||
;; file version, filename, date, etc
|
||||
((info file-info :overlay-at id)
|
||||
;; visibility bitstring with a bit set for every visid
|
||||
;; used in this level
|
||||
(all-visible-list (pointer uint16))
|
||||
;; number of bits in visibility list for this level
|
||||
(visible-list-length int32)
|
||||
;; All the level models/collision
|
||||
(drawable-trees drawable-tree-array)
|
||||
(pat pointer)
|
||||
;; PAT describes the attributes of a collision triangle.
|
||||
;; To avoid storing a full 32-bit PAT per triangle,
|
||||
;; triangles typicall store an 8-bit index into
|
||||
;; this array.
|
||||
(pat (pointer pat-surface))
|
||||
(pat-length int32)
|
||||
;; The level texture pages contain combined textures for all assets in the level.
|
||||
;; art-groups for creatures/actors/enemies/objects within a level don't reference
|
||||
;; this combined texture. This remapping table maps per-art-group texture-ids to
|
||||
;; the combined per-level texture pages. This allows the engine to consume the same
|
||||
;; exact art-group file for an enemy no matter which level is actually providing
|
||||
;; the textures. Background geometry doesn't need this since it's built into
|
||||
;; the bsp file and contains reference to the combined texture-pages already.
|
||||
(texture-remap-table (pointer uint64))
|
||||
(texture-remap-table-len int32)
|
||||
|
||||
;; a single texture-id for each texture-page.
|
||||
;; the textures aren't contained in the bsp-header.
|
||||
;; this allows a level to find its textures, which are hopefully loaded
|
||||
;; prior to the level.
|
||||
(texture-ids (pointer texture-id))
|
||||
(texture-page-count int32)
|
||||
|
||||
;; unused.
|
||||
(unk-zero-0 basic)
|
||||
(name symbol)
|
||||
(nickname symbol)
|
||||
|
||||
;; level visibility data for this level plus 6 neighbors, plus 1 null-terminator.
|
||||
(vis-info level-vis-info 8)
|
||||
|
||||
;; all the entity-actors. Each entity-actor defines how to spawn a process.
|
||||
(actors drawable-inline-array-actor)
|
||||
|
||||
;; all the hand-scripted cameras in the level
|
||||
(cameras (array entity-camera))
|
||||
|
||||
;; actual BSP structure
|
||||
(nodes (inline-array bsp-node))
|
||||
|
||||
;; edited at runtime: link to runtime level structure for this level
|
||||
(level level)
|
||||
|
||||
;; edited at runtime: current bsp leaf index for camera position
|
||||
(current-leaf-idx uint16)
|
||||
(unk-data-2 uint16 9)
|
||||
|
||||
;; boundary of the level as an array of boxes.
|
||||
(boxes box8s-array)
|
||||
;; Packed neighboring-level flags from the terminal BSP side containing the camera.
|
||||
(current-bsp-back-flags uint32)
|
||||
;; edited at runtime: the leaf bsp flags
|
||||
(current-bsp-flags uint32)
|
||||
|
||||
;; effects in the level (sounds, music changes, etc)
|
||||
(ambients drawable-inline-array-ambient)
|
||||
(unk-data-4 float)
|
||||
(unk-data-5 float)
|
||||
|
||||
;; per-level settings for terrain mesh level-of-detail.
|
||||
(subdivide-close-distance meters)
|
||||
(subdivide-far-distance meters)
|
||||
|
||||
;; all the "shaders" (texture + GS rendering settings) for background drawing.
|
||||
(adgifs adgif-shader-array)
|
||||
|
||||
;; order that actors should be birthed.
|
||||
(actor-birth-order (pointer uint32))
|
||||
|
||||
;; seems to be diagnostic only, an index per each box in boxes.
|
||||
(split-box-indices (pointer uint16))
|
||||
|
||||
;; unused?
|
||||
(unk-data-8 uint32 55))
|
||||
(:methods
|
||||
(relocate (_type_ kheap (pointer uint8)) none :replace)
|
||||
(birth (_type_) none)
|
||||
(deactivate-entities (_type_) none)))
|
||||
|
||||
;; Minimal wrapper around a master BSP. Runtime levels normally use bsp-header directly.
|
||||
;; Minimal wrapper around a master BSP. Unused.
|
||||
(deftype game-level (basic)
|
||||
((master-bsp basic)))
|
||||
|
||||
;; View frustum, stored as vertices, using absurd "hither" and "yonder" for near and far.
|
||||
(deftype view-frustum (structure)
|
||||
((hither-top-left vector :inline)
|
||||
(hither-top-right vector :inline)
|
||||
@@ -112,6 +183,9 @@
|
||||
(if (> (-> node back) 0) (map-bsp-tree visit header (the-as bsp-node (-> node back))) (visit node))))
|
||||
(none))
|
||||
|
||||
;; collision statistic. The collision statistics are mostly broken and
|
||||
;; likely were from earlier collision code, or were only enabled with a
|
||||
;; compile-time flag.
|
||||
(deftype cl-stat (structure)
|
||||
((fragments uint32)
|
||||
(tris uint32)
|
||||
|
||||
@@ -328,8 +328,8 @@
|
||||
(b! #t cfg-1 :delay (set! next-node (the-as bsp-node (-> node back))))
|
||||
(label cfg-4)
|
||||
(set! (-> header current-leaf-idx) (the-as uint next-node))
|
||||
;; Despite its name, this holds the flags for whichever terminal side was selected.
|
||||
(set! (-> header current-bsp-back-flags) side-flags)))
|
||||
(set! (-> header current-bsp-flags) side-flags)
|
||||
))
|
||||
0
|
||||
(none))))
|
||||
|
||||
|
||||
@@ -585,8 +585,8 @@
|
||||
;; done!
|
||||
(set! (-> loaded-level nickname) (-> loaded-level bsp nickname))
|
||||
(if (nonzero? (-> loaded-level bsp nodes)) (set! *time-of-day-effects* #t) (set! *time-of-day-effects* #f))
|
||||
(let ((close-distance (-> loaded-level bsp unk-data-4))
|
||||
(far-distance (-> loaded-level bsp unk-data-5)))
|
||||
(let ((close-distance (-> loaded-level bsp subdivide-close-distance))
|
||||
(far-distance (-> loaded-level bsp subdivide-far-distance)))
|
||||
(when (and (= close-distance 0.0) (= far-distance 0.0))
|
||||
(set! close-distance 122880.0)
|
||||
(set! far-distance 286720.0))
|
||||
@@ -1289,7 +1289,7 @@
|
||||
(dotimes (level-index (-> this length))
|
||||
(let ((active-level (-> this level level-index)))
|
||||
(when (= (-> active-level status) 'active)
|
||||
(let ((border-flags (-> active-level bsp current-bsp-back-flags)))
|
||||
(let ((border-flags (-> active-level bsp current-bsp-flags)))
|
||||
(dotimes (neighbor-index 6)
|
||||
(when (and (logtest? border-flags 3) (-> active-level vis-info (+ neighbor-index 1)))
|
||||
(let ((neighbor-info (lookup-level-info (-> active-level vis-info (+ neighbor-index 1) from-level))))
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
;; A dynamics profile defines the local up direction, gravity acceleration and
|
||||
;; terminal fall speed used by a moving object. gravity points upward so callers
|
||||
;; negate it when applying acceleration; gravity-normal is the corresponding unit
|
||||
;; vector. The profile also carries named walking and running distances.
|
||||
;; vector.
|
||||
(deftype dynamics (basic)
|
||||
((name basic)
|
||||
(gravity-max meters)
|
||||
|
||||
@@ -2,18 +2,17 @@
|
||||
(in-package goal)
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "engine/game/game-h.gc")
|
||||
|
||||
(declare-type snowball-info basic)
|
||||
|
||||
(declare-type tube-info basic)
|
||||
|
||||
(declare-type racer-info basic)
|
||||
|
||||
(declare-type flut-info basic)
|
||||
|
||||
(declare-type sidekick process-drawable)
|
||||
|
||||
;; Jak and Daxter's process types and the core target entry points. Most movement and collision
|
||||
;; state lives in control-info, which occupies the process-drawable root slot.
|
||||
;; target is the player character.
|
||||
;; The name is probably from camera code, which refers to the thing being tracked as "target".
|
||||
;; In math-camera, there's also an unused function `move-target-from-pad`, which likely was
|
||||
;; used to move the camera target when testing very early camera code.
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
@@ -34,7 +33,7 @@
|
||||
(attack-info-rec attack-info :inline) ;; Most recently received attack description.
|
||||
(anim-seed uint64) ;; Shared with Daxter to synchronize ambient animation.
|
||||
(alt-cam-pos vector :inline) ;; Camera focus override selected by state-flags.
|
||||
(snowball snowball-info) ;; Snowball-riding state.
|
||||
(snowball snowball-info) ;; Snowball-riding state. (snowball is unimplemented)
|
||||
(tube tube-info) ;; Tube-riding state.
|
||||
(flut flut-info) ;; Flut Flut riding state.
|
||||
(current-level level) ;; Current level used for in-level time accounting.
|
||||
@@ -189,7 +188,7 @@
|
||||
((parent-override (pointer target) :overlay-at parent)
|
||||
(control control-info :overlay-at root)
|
||||
(anim-seed uint64 :offset 192) ;; Mirrors Jak's ambient-animation seed.
|
||||
(shadow-in-movie? symbol)) ;; Permit Daxter's special shadow during movies.
|
||||
(shadow-in-movie? symbol)) ;; Permit Daxter's shadow during movies.
|
||||
(:states
|
||||
sidekick-clone))
|
||||
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "kernel-defs.gc")
|
||||
|
||||
;; The sync-info types derive repeatable phases from the global game clock so
|
||||
;; independently updated objects remain synchronized. Platforms can therefore
|
||||
;; share a period and retain consistent relative positions without communicating
|
||||
;; every frame.
|
||||
;; The sync-info types keep gameplay objects like platforms in sync.
|
||||
;; Platforms may spawn and despawn during gameplay, and determine their
|
||||
;; momvement phase from the global clock.
|
||||
;;
|
||||
;; This file also contains small randomized and spring-like motion controls that
|
||||
;; do not use the synchronization clock.
|
||||
@@ -14,8 +13,8 @@
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; The base clock produces a sawtooth phase from 0 to 1 over each period. Its
|
||||
;; mirrored form produces a triangular phase from 0 to 1 and back to 0 over the
|
||||
;; same period. Citadel's rotating "pies" are synchronized with this clock.
|
||||
;; mirrored versions produces a triangular phase from 0 to 1 and back to 0 over the
|
||||
;; same period.
|
||||
(deftype sync-info (structure)
|
||||
(;; Phase offset stored in game-time ticks rather than normalized phase.
|
||||
(offset float)
|
||||
@@ -107,8 +106,7 @@
|
||||
(at-min? (_type_) symbol)
|
||||
(at-max? (_type_) symbol)))
|
||||
|
||||
;; Vector counterpart to delayed-rand-float. X and Z share one symmetric range,
|
||||
;; Y has its own, and W remains zero.
|
||||
;; Vector counterpart to delayed-rand-float.
|
||||
(deftype delayed-rand-vector (structure)
|
||||
((min-time int32)
|
||||
(max-time int32)
|
||||
|
||||
Reference in New Issue
Block a user