first pass at cam cleanup

This commit is contained in:
water111
2026-08-07 20:58:40 -04:00
parent c3d5817425
commit 2929a106aa
15 changed files with 2890 additions and 2842 deletions
+55
View File
@@ -737,6 +737,7 @@ void Env::rebuild_stack_slot_use_def_info() {
int next_var_id = 1;
for (int offset : offsets) {
const int first_var_id = next_var_id;
std::vector<bool> reads_before_write(block_count, false);
std::vector<bool> writes(block_count, false);
@@ -784,6 +785,7 @@ void Env::rebuild_stack_slot_use_def_info() {
std::vector<int> phi_var(block_count, -1);
std::vector<std::vector<int>> phi_sources(block_count);
std::vector<int> access_ops;
for (int block_id = 0; block_id < block_count; block_id++) {
if (live_in.at(block_id)) {
phi_var.at(block_id) = next_var_id++;
@@ -801,6 +803,7 @@ void Env::rebuild_stack_slot_use_def_info() {
}
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);
@@ -810,6 +813,7 @@ void Env::rebuild_stack_slot_use_def_info() {
}
current_var = next_var_id++;
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.defs.push_back({op_id, block_id, AccessMode::WRITE, false});
info.ssa_vars.insert(current_var);
@@ -839,6 +843,57 @@ void Env::rebuild_stack_slot_use_def_info() {
info.uses.push_back({first_op, block_id, AccessMode::READ, false});
}
}
// Match register variable analysis by merging every live stack-slot phi with its incoming
// definitions. Without this, a conditional store and the loads after its control-flow join
// receive different program-variable IDs even though they are one mutable source variable.
std::vector<int> parent(next_var_id - first_var_id);
for (int i = 0; i < (int)parent.size(); i++) {
parent.at(i) = first_var_id + i;
}
auto find_root = [&](int var) {
int root = var;
while (parent.at(root - first_var_id) != root) {
root = parent.at(root - first_var_id);
}
while (parent.at(var - first_var_id) != var) {
const int next = parent.at(var - first_var_id);
parent.at(var - first_var_id) = root;
var = next;
}
return root;
};
for (int block_id = 0; block_id < block_count; block_id++) {
if (phi_var.at(block_id) == -1) {
continue;
}
const int phi_root = find_root(phi_var.at(block_id));
for (int src_var : phi_sources.at(block_id)) {
parent.at(find_root(src_var) - first_var_id) = phi_root;
}
}
std::unordered_map<int, UseDefInfo> merged_info;
for (int var = first_var_id; var < next_var_id; var++) {
const int root = find_root(var);
auto& merged = merged_info[root];
merged.ssa_vars.insert(var);
const RegId old_id(Register(Reg::GPR, Reg::SP), var);
auto old = m_stack_slot_use_def_info.find(old_id);
if (old != m_stack_slot_use_def_info.end()) {
merged.defs.insert(merged.defs.end(), old->second.defs.begin(), old->second.defs.end());
merged.uses.insert(merged.uses.end(), old->second.uses.begin(), old->second.uses.end());
merged.ssa_vars.insert(old->second.ssa_vars.begin(), old->second.ssa_vars.end());
m_stack_slot_use_def_info.erase(old);
}
}
for (auto& [root, info] : merged_info) {
m_stack_slot_use_def_info.emplace(RegId(Register(Reg::GPR, Reg::SP), root), std::move(info));
}
for (int op_id : access_ops) {
m_stack_slot_var_by_op.at(op_id) = find_root(m_stack_slot_var_by_op.at(op_id));
}
}
}
+11 -83
View File
@@ -185,40 +185,6 @@ FormElement* rewrite_as_dotimes(LetElement* in, const Env& env, FormPool& pool)
return rewrite_as_dotimes(entry.dest, loop, env, pool);
}
bool program_var_is_confined_to(const Form* top_level_form,
const RegId& var,
FormElement* init,
FormElement* loop,
const Env& env) {
RegAccessSet all_accesses;
top_level_form->collect_vars(all_accesses, true);
RegAccessSet confined_accesses;
init->collect_vars(confined_accesses, true);
loop->collect_vars(confined_accesses, true);
for (const auto& access : all_accesses) {
if (env.get_program_var_id(access) == var && !confined_accesses.count(access)) {
return false;
}
}
return true;
}
bool program_var_shares_name(const Form* top_level_form,
const RegId& var,
const std::string& name,
const Env& env) {
RegAccessSet all_accesses;
top_level_form->collect_vars(all_accesses, true);
for (const auto& access : all_accesses) {
if (env.get_program_var_id(access) != var && env.get_variable_name(access) == name) {
return true;
}
}
return false;
}
std::tuple<MatchResult, Form*, bool> rewrite_shelled_return_form(
const Matcher& matcher,
FormElement* in,
@@ -4245,47 +4211,9 @@ LetStats insert_lets(const Function& func,
// }
LetStats stats;
// A deliberately reused display name can cause otherwise independent program variables to be
// grouped together by let insertion. Recognize the unshelled expansion before inserting lets
// when the counter's complete lifetime is confined to the adjacent set!/while pair. Doing this
// here keeps a following co-named loop from being pulled into the first counter's let body, while
// preserving the existing behavior for co-named variables in every other situation.
top_level_form->apply_form([&](Form* f) {
auto& elts = f->elts();
for (size_t i = 0; i + 1 < elts.size();) {
auto* init = dynamic_cast<SetVarElement*>(elts.at(i));
if (!init || !register_can_hold_var(init->dst().reg()) ||
init->info().is_eliminated_coloring_move || !is_constant_int(init->src(), 0)) {
i++;
continue;
}
const auto var = env.get_program_var_id(init->dst());
const auto name = env.get_variable_name(init->dst());
if (!program_var_shares_name(top_level_form, var, name, env) ||
!program_var_is_confined_to(top_level_form, var, init, elts.at(i + 1), env)) {
i++;
continue;
}
auto* dotimes = rewrite_as_dotimes(init->dst(), elts.at(i + 1), env, pool);
if (!dotimes) {
i++;
continue;
}
dotimes->parent_form = f;
elts.at(i) = dotimes;
elts.erase(elts.begin() + i + 1);
env.set_defined_in_let(name);
let_rewrite_stats.dotimes++;
i++;
}
});
// Stored per variable.
struct PerVarInfo {
std::string unique_name; // displayed name used to join deliberately co-named SSA variables
std::string display_name;
RegisterAccess access;
std::unordered_set<FormElement*> elts_using_var; // all FormElements using var
Form* lca_form = nullptr; // the lowest common form that contains all the above elts
@@ -4293,7 +4221,7 @@ LetStats insert_lets(const Function& func,
int end_idx = -1; // in the above form, 1 + last FormElement using var's index
};
std::unordered_map<std::string, PerVarInfo> var_info;
std::unordered_map<RegId, PerVarInfo, RegId::hash> var_info;
// Part 1, figure out which forms reference each var
top_level_form->apply([&](FormElement* elt) {
@@ -4318,10 +4246,10 @@ LetStats insert_lets(const Function& func,
// and add it.
for (auto& access : reg_accesses) {
if (register_can_hold_var(access.reg())) {
auto unique_name = env.get_variable_name(access);
var_info[unique_name].elts_using_var.insert(elt);
var_info[unique_name].unique_name = unique_name;
var_info[unique_name].access = access;
const auto var = env.get_program_var_id(access);
var_info[var].elts_using_var.insert(elt);
var_info[var].display_name = env.get_variable_name(access);
var_info[var].access = access;
}
}
});
@@ -4336,7 +4264,7 @@ LetStats insert_lets(const Function& func,
lca = lca_form(lca, fe->parent_form, env);
}
ASSERT(lca);
var_info[kv.first].lca_form = lca;
kv.second.lca_form = lca;
}
// Part 3, find the minimum range of FormElement's within the lca form that contain
@@ -4353,7 +4281,7 @@ LetStats insert_lets(const Function& func,
bool uses = false;
for (auto& ra : ras) {
if ((ra.reg().get_kind() == Reg::FPR || ra.reg().get_kind() == Reg::GPR) &&
env.get_variable_name(ra) == kv.second.unique_name) {
env.get_program_var_id(ra) == kv.first) {
uses = true;
}
}
@@ -4399,7 +4327,7 @@ LetStats insert_lets(const Function& func,
auto first_form = info.lca_form->at(info.start_idx);
auto first_form_as_set = dynamic_cast<SetVarElement*>(first_form);
if (first_form_as_set && register_can_hold_var(first_form_as_set->dst().reg()) &&
env.get_variable_name(first_form_as_set->dst()) == env.get_variable_name(info.access) &&
env.get_program_var_id(first_form_as_set->dst()) == env.get_program_var_id(info.access) &&
!first_form_as_set->info().is_eliminated_coloring_move) {
bool allowed = true;
@@ -4422,12 +4350,12 @@ LetStats insert_lets(const Function& func,
li.start_elt = info.start_idx;
li.end_elt = info.end_idx;
li.set_form = first_form_as_set;
li.name = info.unique_name;
li.name = info.display_name;
possible_insertions[li.form].push_back(li);
stats.vars_in_lets++;
}
} else {
// lg::print("fail for {} : {}\n", info.var_name, first_form->to_string(env));
// lg::print("fail for {} : {}\n", info.display_name, first_form->to_string(env));
}
}
+177 -198
View File
@@ -4,7 +4,6 @@
(require "engine/gfx/hw/display.gc")
(require "engine/camera/camera.gc")
;; DECOMP BEGINS
;; Blend the active camera slaves into the single transform used for rendering.
;; The complexity here is around camera orientation. Orientations are interpolated
@@ -25,10 +24,12 @@
;; (copy-tracking (source camera-slave))
;; Adopt source's tracking controls together with its current follow state and rotation,
;; avoiding a discontinuity when an already tracking slave is handed to the combiner.
;; DECOMP BEGINS
(defstate cam-combiner-active (camera-combiner)
:event
(behavior ((proc process) (argc int) (message symbol) (block event-message-block))
(local-vars (source-slave camera-slave))
(case message
(('point-of-interest)
(cond
@@ -36,7 +37,9 @@
(set! (-> self tracking use-point-of-interest) #t)
(set! (-> self tracking point-of-interest quad) (-> (the-as vector (-> block param 0)) quad))
(set! (-> self tracking point-of-interest-blend target) 1.0))
(else (set! (-> self tracking use-point-of-interest) #f) (set! (-> self tracking point-of-interest-blend target) 0.0))))
(else
(set! (-> self tracking use-point-of-interest) #f)
(set! (-> self tracking point-of-interest-blend target) 0.0))))
(('set-interpolation)
(set! (-> self interp-val) 0.0)
(set! (-> self interp-step) (/ 5.0 (the float (-> block param 0)))))
@@ -48,7 +51,9 @@
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#f)))
(('stop-tracking) (set! (-> self tracking-status) (cam-track-status use-slave-tracking)) 0)
(('stop-tracking)
(set! (-> self tracking-status) (cam-track-status use-slave-tracking))
0)
(('start-tracking)
(cond
((< argc 1)
@@ -59,21 +64,21 @@
(format 0 "ERROR <GMJ>: invalid type '~A' to *camera-combiner* start-tracking~%" (rtype-of (-> block param 0))))
((= (-> self tracking-status) (cam-track-status use-slave-tracking))
(set! (-> self tracking-status) (cam-track-status track-at-combiner))
(set! source-slave (the-as camera-slave (-> block param 0)))
(set! (-> self tracking-options) (the-as cam-slave-options-i (-> source-slave options)))
(set! (-> self tracking no-follow) (-> source-slave tracking no-follow))
(copy-cam-float-seeker (-> self tracking tilt-adjust) (-> source-slave tracking tilt-adjust))
(copy-cam-float-seeker (-> self tracking underwater-blend) (-> source-slave tracking underwater-blend))
(set! (-> self tracking use-point-of-interest) (-> source-slave tracking use-point-of-interest))
(vector-copy! (-> self tracking point-of-interest) (-> source-slave tracking point-of-interest))
(copy-cam-float-seeker (-> self tracking point-of-interest-blend) (-> source-slave tracking point-of-interest-blend))
(let ((source-position (-> source-slave trans)))
(cam-calc-follow! (-> self tracking) source-position #f)
(slave-set-rotation! (-> self tracking)
source-position
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#f)))))
(let ((source-slave (the-as camera-slave (-> block param 0))))
(set! (-> self tracking-options) (the-as cam-slave-options-i (-> source-slave options)))
(set! (-> self tracking no-follow) (-> source-slave tracking no-follow))
(copy-cam-float-seeker (-> self tracking tilt-adjust) (-> source-slave tracking tilt-adjust))
(copy-cam-float-seeker (-> self tracking underwater-blend) (-> source-slave tracking underwater-blend))
(set! (-> self tracking use-point-of-interest) (-> source-slave tracking use-point-of-interest))
(vector-copy! (-> self tracking point-of-interest) (-> source-slave tracking point-of-interest))
(copy-cam-float-seeker (-> self tracking point-of-interest-blend) (-> source-slave tracking point-of-interest-blend))
(let ((source-position (-> source-slave trans)))
(cam-calc-follow! (-> self tracking) source-position #f)
(slave-set-rotation! (-> self tracking)
source-position
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#f))))))
(('copy-tracking)
(cond
((< argc 1)
@@ -85,17 +90,17 @@
((nonzero? (-> self tracking-status)) #f)
(else
(set! (-> self tracking-status) (cam-track-status track-at-combiner))
(set! source-slave (the-as camera-slave (-> block param 0)))
(set! (-> self tracking-options) (the-as cam-slave-options-i (-> source-slave options)))
(set! (-> self tracking no-follow) (-> source-slave tracking no-follow))
(copy-cam-float-seeker (-> self tracking tilt-adjust) (-> source-slave tracking tilt-adjust))
(copy-cam-float-seeker (-> self tracking underwater-blend) (-> source-slave tracking underwater-blend))
(vector-copy! (-> self tracking follow-off) (-> source-slave tracking follow-off))
(vector-copy! (-> self tracking follow-pt) (-> source-slave tracking follow-pt))
(matrix-copy! (-> self tracking inv-mat) (-> source-slave tracking inv-mat))
(set! (-> self tracking use-point-of-interest) (-> source-slave tracking use-point-of-interest))
(vector-copy! (-> self tracking point-of-interest) (-> source-slave tracking point-of-interest))
(copy-cam-float-seeker (-> self tracking point-of-interest-blend) (-> source-slave tracking point-of-interest-blend)))))))
(let ((source-slave (the-as camera-slave (-> block param 0))))
(set! (-> self tracking-options) (the-as cam-slave-options-i (-> source-slave options)))
(set! (-> self tracking no-follow) (-> source-slave tracking no-follow))
(copy-cam-float-seeker (-> self tracking tilt-adjust) (-> source-slave tracking tilt-adjust))
(copy-cam-float-seeker (-> self tracking underwater-blend) (-> source-slave tracking underwater-blend))
(vector-copy! (-> self tracking follow-off) (-> source-slave tracking follow-off))
(vector-copy! (-> self tracking follow-pt) (-> source-slave tracking follow-pt))
(matrix-copy! (-> self tracking inv-mat) (-> source-slave tracking inv-mat))
(set! (-> self tracking use-point-of-interest) (-> source-slave tracking use-point-of-interest))
(vector-copy! (-> self tracking point-of-interest) (-> source-slave tracking point-of-interest))
(copy-cam-float-seeker (-> self tracking point-of-interest-blend) (-> source-slave tracking point-of-interest-blend))))))))
:code
(behavior ()
(local-vars (output-matrix matrix))
@@ -119,176 +124,148 @@
(previous-position (new-stack-vector0)))
(vector-copy! previous-position (-> self trans))
(if source-slave
(set! output-matrix
(cond
(destination-slave
;; Position and FOV can be interpolated directly. Rotation is blended as
;; an axis-angle below so that the resulting camera basis stays orthonormal.
(vector-lerp-clamp! (-> self trans) (-> source-slave 0 trans) (-> destination-slave 0 trans) blend)
(set! (-> self fov) (lerp-clamp (-> source-slave 0 fov) (-> destination-slave 0 fov) blend))
(set! (-> self dist-from-src) (vector-vector-distance (-> self trans) (-> source-slave 0 trans)))
(set! (-> self dist-from-dest) (vector-vector-distance (-> self trans) (-> destination-slave 0 trans)))
(set! output-matrix
(cond
((= (-> self tracking-status) (cam-track-status track-at-combiner))
(cam-calc-follow! (-> self tracking) (-> self trans) #t)
(slave-set-rotation! (-> self tracking)
(-> self trans)
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#t)
(matrix-copy! (-> self inv-camera-rot) (-> self tracking inv-mat)))
(else
(let ((source-tracker (-> source-slave 0 tracking))
(source-position (-> source-slave 0 trans))
(destination-tracker (-> destination-slave 0 tracking))
(destination-position (-> destination-slave 0 trans)))
(cond
((= (-> self tracking-status) (cam-track-status track-at-src))
(cam-calc-follow! (-> self tracking) source-position #t)
(slave-set-rotation! (-> self tracking)
source-position
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#t)
(set! source-tracker (-> self tracking))
(set! source-position (-> self trans)))
((= (-> self tracking-status) (cam-track-status track-at-dst))
(cam-calc-follow! (-> self tracking) destination-position #t)
(slave-set-rotation! (-> self tracking)
destination-position
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#t)
(set! destination-tracker (-> self tracking))
(set! destination-position (-> self trans))))
;; Corresponding rows of two rotation bases differ in directions
;; perpendicular to their shared axis of rotation. Cross the two
;; strongest row deltas, omitting the row which changed least, to
;; recover a stable rotation axis.
(let ((rotation-work (new 'stack-no-clear 'matrix)))
(dotimes (i 3)
(set! (-> rotation-work vector i quad) (the-as uint128 0)))
0.0
0.0
0.0
(let ((rotation-axis (new-stack-vector0)))
(set! output-matrix
(cond
(destination-slave
(vector-lerp-clamp! (-> self trans) (-> source-slave 0 trans) (-> destination-slave 0 trans) blend)
(set! (-> self fov) (lerp-clamp (-> source-slave 0 fov) (-> destination-slave 0 fov) blend))
(set! (-> self dist-from-src) (vector-vector-distance (-> self trans) (-> source-slave 0 trans)))
(set! (-> self dist-from-dest) (vector-vector-distance (-> self trans) (-> destination-slave 0 trans)))
(set! output-matrix
(cond
((= (-> self tracking-status) (cam-track-status track-at-combiner))
(cam-calc-follow! (-> self tracking) (-> self trans) #t)
(slave-set-rotation! (-> self tracking)
(-> self trans)
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#t)
(matrix-copy! (-> self inv-camera-rot) (-> self tracking inv-mat)))
(else
(let ((source-tracker (-> source-slave 0 tracking))
(source-position (-> source-slave 0 trans))
(destination-tracker (-> destination-slave 0 tracking))
(destination-position (-> destination-slave 0 trans)))
(cond
((= (-> self tracking-status) (cam-track-status track-at-src))
(cam-calc-follow! (-> self tracking) source-position #t)
(slave-set-rotation! (-> self tracking)
source-position
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#t)
(set! source-tracker (-> self tracking))
(set! source-position (-> self trans)))
((= (-> self tracking-status) (cam-track-status track-at-dst))
(cam-calc-follow! (-> self tracking) destination-position #t)
(slave-set-rotation! (-> self tracking)
destination-position
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#t)
(set! destination-tracker (-> self tracking))
(set! destination-position (-> self trans))))
(let ((rotation-work (new 'stack-no-clear 'matrix)))
(dotimes (i 3)
(set! (-> rotation-work vector i quad) (the-as uint128 0)))
0.0
(let ((rotation-matrix (new-stack-matrix0)))
(vector-! (-> rotation-work vector 0)
(the-as vector (-> source-tracker inv-mat))
(the-as vector (-> destination-tracker inv-mat)))
(vector-! (-> rotation-work vector 1) (-> source-tracker inv-mat vector 1) (-> destination-tracker inv-mat vector 1))
(vector-! (-> rotation-work vector 2) (-> source-tracker inv-mat vector 2) (-> destination-tracker inv-mat vector 2))
(let ((row-0-delta (vector-length (-> rotation-work vector 0)))
(row-1-delta (vector-length (-> rotation-work vector 1)))
(row-2-delta (vector-length (-> rotation-work vector 2))))
(cond
((and (< row-0-delta row-1-delta) (< row-0-delta row-2-delta))
(vector-cross! rotation-axis (-> rotation-work vector 1) (-> rotation-work vector 2)))
((and (< row-1-delta row-0-delta) (< row-1-delta row-2-delta))
(vector-cross! rotation-axis (-> rotation-work vector 0) (-> rotation-work vector 2)))
(else (vector-cross! rotation-axis (-> rotation-work vector 0) (-> rotation-work vector 1)))))
(vector-normalize! rotation-axis 1.0)
;; Choose the source basis row least parallel to the axis,
;; then project that row and its destination counterpart into
;; the plane normal to the axis. Their planar angle is the
;; amount of rotation separating the two camera bases.
(let ((row-0-axis-dot (fabs (vector-dot (the-as vector (-> source-tracker inv-mat)) rotation-axis)))
(row-1-axis-dot (fabs (vector-dot (-> source-tracker inv-mat vector 1) rotation-axis)))
(row-2-axis-dot (fabs (vector-dot (-> source-tracker inv-mat vector 2) rotation-axis))))
(cond
((and (< row-0-axis-dot row-1-axis-dot) (< row-0-axis-dot row-2-axis-dot))
(vector-flatten! (-> rotation-work vector 0) (the-as vector (-> source-tracker inv-mat)) rotation-axis)
(vector-flatten! (-> rotation-work vector 1) (the-as vector (-> destination-tracker inv-mat)) rotation-axis))
((< row-1-axis-dot row-2-axis-dot)
(vector-flatten! (-> rotation-work vector 0) (-> source-tracker inv-mat vector 1) rotation-axis)
(vector-flatten! (-> rotation-work vector 1) (-> destination-tracker inv-mat vector 1) rotation-axis))
(else
(vector-flatten! (-> rotation-work vector 0) (-> source-tracker inv-mat vector 2) rotation-axis)
(vector-flatten! (-> rotation-work vector 1) (-> destination-tracker inv-mat vector 2) rotation-axis))))
(vector-normalize! (-> rotation-work vector 0) 1.0)
(vector-normalize! (-> rotation-work vector 1) 1.0)
(vector-cross! (-> rotation-work vector 2) (-> rotation-work vector 0) (-> rotation-work vector 1))
;; Orient the otherwise sign-ambiguous axis to agree with the
;; direction from the projected source row to destination row.
(if (< (vector-dot (-> rotation-work vector 2) rotation-axis) 0.0) (vector-negate! rotation-axis rotation-axis))
(let ((rotation-angle (acos (vector-dot (-> rotation-work vector 0) (-> rotation-work vector 1)))))
(cond
;; A newly activated slave starts a new arc decision, so
;; discard both the one-shot marker and the previous flip.
((logtest? (-> *camera* master-options) (cam-master-options set-combiner-axis))
(logclear! (-> *camera* master-options) (cam-master-options set-combiner-axis flip-combiner))
;; Compare the target and destination directions in the
;; local horizontal plane. The final test has no body in
;; this version and therefore has no observable effect.
(when (and (< 8192.0 rotation-angle) (logtest? (-> *camera* master-options) (cam-master-options have-target)))
(vector-! (-> rotation-work vector 0) (-> *camera* tpos-curr) source-position)
(vector-! (-> rotation-work vector 1) destination-position source-position)
(vector-flatten! (-> rotation-work vector 0) (-> rotation-work vector 0) (-> *camera* local-down))
(vector-flatten! (-> rotation-work vector 1) (-> rotation-work vector 1) (-> *camera* local-down))
(when (and (< 4096.0 (vector-normalize-ret-len! (-> rotation-work vector 0) 1.0))
(< 4096.0 (vector-normalize-ret-len! (-> rotation-work vector 1) 1.0)))
(vector-cross! (-> rotation-work vector 2) (-> rotation-work vector 1) (-> rotation-work vector 0))
(when (< (vector-dot (-> rotation-work vector 2) rotation-axis) -0.01)))))
;; For rotations over 90 degrees, keep the chosen axis
;; continuous across frames by switching to the equivalent
;; complementary axis-angle representation when necessary.
((and (< 16384.0 rotation-angle) (< (vector-dot (-> self flip-control-axis) rotation-axis) 0.0))
(logxor! (-> *camera* master-options) (cam-master-options flip-combiner))))
(vector-copy! (-> self flip-control-axis) rotation-axis)
(when (logtest? (-> *camera* master-options) (cam-master-options flip-combiner))
(set! rotation-angle (- 65536.0 rotation-angle))
(vector-negate! rotation-axis rotation-axis))
;; Rotate backward from the destination basis by the portion
;; still separating it from the source: the full angle at
;; blend 0 and no correction at blend 1.
(let ((remaining-angle (* rotation-angle (- 1.0 blend))))
(matrix-axis-sin-cos! rotation-matrix rotation-axis (sin remaining-angle) (cos remaining-angle))))
(matrix*! (-> self inv-camera-rot) (-> destination-tracker inv-mat) rotation-matrix)))))
output-matrix)))
;; Do not advance the blend while the outgoing slave is still reaching its
;; authored exit point or while the game is paused.
(cond
((and (< 0.0 (-> *camera* outro-t-step)) (< (-> *camera* outro-t) (-> *camera* outro-exit-value))))
((and (< (-> *camera* outro-t-step) 0.0) (< (-> *camera* outro-exit-value) (-> *camera* outro-t))))
((paused?))
(else (+! (-> self interp-val) (* (-> self interp-step) (-> *display* time-adjust-ratio)))))
;; Once the blend reaches its destination, retire the outgoing slave and
;; promote the destination into slot 0.
(when (>= (-> self interp-val) 1.0)
(deactivate (-> *camera* slave 0 0))
(set! (-> *camera* slave 0) (-> *camera* slave 1))
(set! (-> *camera* slave 1) (the-as (pointer camera-slave) #f))
(+! (-> *camera* num-slaves) -1))
output-matrix)
(else
(set! (-> self dist-from-src) 409600.0)
(set! (-> self dist-from-dest) 0.0)
(vector-copy! (-> self trans) (-> source-slave 0 trans))
(set! (-> self fov) (-> source-slave 0 fov))
;; Resolve the endpoint-only tracking modes after a transition has left just
;; one slave: destination tracking becomes steady combiner tracking, while
;; source tracking ends with the retired source.
(cond
((= (-> self tracking-status) (cam-track-status track-at-dst))
(set! (-> self tracking-status) (cam-track-status track-at-combiner)))
((= (-> self tracking-status) (cam-track-status track-at-src))
(set! (-> self tracking-status) (cam-track-status use-slave-tracking))
0))
(cond
((= (-> self tracking-status) (cam-track-status track-at-combiner))
(cam-calc-follow! (-> self tracking) (-> self trans) #t)
(slave-set-rotation! (-> self tracking)
(-> self trans)
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#t)
(matrix-copy! (-> self inv-camera-rot) (-> self tracking inv-mat)))
(else (matrix-copy! (-> self inv-camera-rot) (-> source-slave 0 tracking inv-mat))))))))
0.0
0.0
(let ((rotation-axis (new-stack-vector0)))
0.0
(let ((rotation-matrix (new-stack-matrix0)))
(vector-! (-> rotation-work vector 0) (-> source-tracker inv-mat vector 0) (-> destination-tracker inv-mat vector 0))
(vector-! (-> rotation-work vector 1) (-> source-tracker inv-mat vector 1) (-> destination-tracker inv-mat vector 1))
(vector-! (-> rotation-work vector 2) (-> source-tracker inv-mat vector 2) (-> destination-tracker inv-mat vector 2))
(let ((row-0-delta (vector-length (-> rotation-work vector 0)))
(row-1-delta (vector-length (-> rotation-work vector 1)))
(row-2-delta (vector-length (-> rotation-work vector 2))))
(cond
((and (< row-0-delta row-1-delta) (< row-0-delta row-2-delta))
(vector-cross! rotation-axis (-> rotation-work vector 1) (-> rotation-work vector 2)))
((and (< row-1-delta row-0-delta) (< row-1-delta row-2-delta))
(vector-cross! rotation-axis (-> rotation-work vector 0) (-> rotation-work vector 2)))
(else
(vector-cross! rotation-axis (-> rotation-work vector 0) (-> rotation-work vector 1)))))
(vector-normalize! rotation-axis 1.0)
(let ((row-0-axis-dot (fabs (vector-dot (-> source-tracker inv-mat vector 0) rotation-axis)))
(row-1-axis-dot (fabs (vector-dot (-> source-tracker inv-mat vector 1) rotation-axis)))
(row-2-axis-dot (fabs (vector-dot (-> source-tracker inv-mat vector 2) rotation-axis))))
(cond
((and (< row-0-axis-dot row-1-axis-dot) (< row-0-axis-dot row-2-axis-dot))
(vector-flatten! (-> rotation-work vector 0) (-> source-tracker inv-mat vector 0) rotation-axis)
(vector-flatten! (-> rotation-work vector 1) (-> destination-tracker inv-mat vector 0) rotation-axis))
((< row-1-axis-dot row-2-axis-dot)
(vector-flatten! (-> rotation-work vector 0) (-> source-tracker inv-mat vector 1) rotation-axis)
(vector-flatten! (-> rotation-work vector 1) (-> destination-tracker inv-mat vector 1) rotation-axis))
(else
(vector-flatten! (-> rotation-work vector 0) (-> source-tracker inv-mat vector 2) rotation-axis)
(vector-flatten! (-> rotation-work vector 1) (-> destination-tracker inv-mat vector 2) rotation-axis))))
(vector-normalize! (-> rotation-work vector 0) 1.0)
(vector-normalize! (-> rotation-work vector 1) 1.0)
(vector-cross! (-> rotation-work vector 2) (-> rotation-work vector 0) (-> rotation-work vector 1))
(if (< (vector-dot (-> rotation-work vector 2) rotation-axis) 0.0)
(vector-negate! rotation-axis rotation-axis))
(let ((rotation-angle (acos (vector-dot (-> rotation-work vector 0) (-> rotation-work vector 1)))))
(cond
((logtest? (-> *camera* master-options) (cam-master-options set-combiner-axis))
(logclear! (-> *camera* master-options) (cam-master-options set-combiner-axis flip-combiner))
(when (and (< 8192.0 rotation-angle) (logtest? (-> *camera* master-options) (cam-master-options have-target)))
(vector-! (-> rotation-work vector 0) (-> *camera* tpos-curr) source-position)
(vector-! (-> rotation-work vector 1) destination-position source-position)
(vector-flatten! (-> rotation-work vector 0) (-> rotation-work vector 0) (-> *camera* local-down))
(vector-flatten! (-> rotation-work vector 1) (-> rotation-work vector 1) (-> *camera* local-down))
(when (and (< 4096.0 (vector-normalize-ret-len! (-> rotation-work vector 0) 1.0))
(< 4096.0 (vector-normalize-ret-len! (-> rotation-work vector 1) 1.0)))
(vector-cross! (-> rotation-work vector 2) (-> rotation-work vector 1) (-> rotation-work vector 0))
(when (< (vector-dot (-> rotation-work vector 2) rotation-axis) -0.01)))))
((and (< 16384.0 rotation-angle) (< (vector-dot (-> self flip-control-axis) rotation-axis) 0.0))
(logxor! (-> *camera* master-options) (cam-master-options flip-combiner))))
(vector-copy! (-> self flip-control-axis) rotation-axis)
(when (logtest? (-> *camera* master-options) (cam-master-options flip-combiner))
(set! rotation-angle (- 65536.0 rotation-angle))
(vector-negate! rotation-axis rotation-axis))
(let ((remaining-angle (* rotation-angle (- 1.0 blend))))
(matrix-axis-sin-cos! rotation-matrix rotation-axis (sin remaining-angle) (cos remaining-angle))))
(matrix*! (-> self inv-camera-rot) (-> destination-tracker inv-mat) rotation-matrix)))))
output-matrix)))
(cond
((and (< 0.0 (-> *camera* outro-t-step)) (< (-> *camera* outro-t) (-> *camera* outro-exit-value))))
((and (< (-> *camera* outro-t-step) 0.0) (< (-> *camera* outro-exit-value) (-> *camera* outro-t))))
((paused?))
(else
(+! (-> self interp-val) (* (-> self interp-step) (-> *display* time-adjust-ratio)))))
(when (>= (-> self interp-val) 1.0)
(deactivate (-> *camera* slave 0 0))
(set! (-> *camera* slave 0) (-> *camera* slave 1))
(set! (-> *camera* slave 1) (the-as (pointer camera-slave) #f))
(+! (-> *camera* num-slaves) -1))
output-matrix)
(else
(set! (-> self dist-from-src) 409600.0)
(set! (-> self dist-from-dest) 0.0)
(vector-copy! (-> self trans) (-> source-slave 0 trans))
(set! (-> self fov) (-> source-slave 0 fov))
(cond
((= (-> self tracking-status) (cam-track-status track-at-dst))
(set! (-> self tracking-status) (cam-track-status track-at-combiner)))
((= (-> self tracking-status) (cam-track-status track-at-src))
(set! (-> self tracking-status) (cam-track-status use-slave-tracking))
0))
(cond
((= (-> self tracking-status) (cam-track-status track-at-combiner))
(cam-calc-follow! (-> self tracking) (-> self trans) #t)
(slave-set-rotation! (-> self tracking)
(-> self trans)
(the-as cam-slave-options (-> self tracking-options))
(-> self fov)
#t)
(matrix-copy! (-> self inv-camera-rot) (-> self tracking inv-mat)))
(else
(matrix-copy! (-> self inv-camera-rot) (-> source-slave 0 tracking inv-mat))))))))
(vector-! (-> self velocity) (-> self trans) previous-position)))
(if (and *dproc* *debug-segment*)
(add-frame (-> *display* frames (-> *display* on-screen) frame profile-bar 0) 'camera (new 'static 'rgba :b #xff :a #x80)))
(add-frame (-> (current-frame) profile-bar 0) 'camera (new 'static 'rgba :b #xff :a #x80)))
(suspend))))
(defbehavior cam-combiner-init camera-combiner ()
@@ -298,7 +275,9 @@
(set! *camera-combiner* self)
(vector-reset! (-> self trans))
(matrix-identity! (-> self inv-camera-rot))
(if *math-camera* (set! (-> self fov) (-> *math-camera* fov)) (set! (-> self fov) 11650.845))
(if *math-camera*
(set! (-> self fov) (-> *math-camera* fov))
(set! (-> self fov) 11650.845))
(set! (-> self interp-val) 0.0)
(set! (-> self interp-step) 0.125)
(set! (-> self tracking-status) (cam-track-status use-slave-tracking))
+30 -38
View File
@@ -29,17 +29,6 @@
(define-extern slave-los-state->string (function slave-los-state string))
(define-extern cam-debug-reset-coll-tri (function none))
; (declare-type clm basic)
; (define-extern *clm* clm)
; (define-extern *clm-edit* clm)
; (define-extern *clm-focalpull-attr* clm)
; (define-extern *clm-index-attr* clm)
; (define-extern *clm-intro-attr* clm)
; (define-extern *clm-spline-attr* clm)
; (define-extern *clm-vol-attr* clm)
; (define-extern *clm-select* clm)
;; DECOMP BEGINS
;; Debug-only rolling histories used by the camera plot display. Each color and
@@ -51,8 +40,8 @@
(define *redline-index* 0)
(defun float-save-redline ((value float))
"Append value to the 400-sample red debug plot, overwriting the oldest sample
when the ring wraps."
"Append value to the 400-sample red debug
plot, overwriting the oldest sample when the ring wraps."
(set! (-> *redline-table* *redline-index*) value)
(set! *redline-index* (+ *redline-index* 1))
(when (>= *redline-index* 400)
@@ -61,17 +50,18 @@
(none))
(defun float-lookup-redline ((position float))
"Read the red debug plot at position in its wrapped drawing order: zero is
newest and one starts at the oldest sample."
(let ((index (mod (+ (the int position) -1 *redline-index*) 400))) (-> *redline-table* index)))
"Read the red debug plot at position in its
wrapped drawing order: zero is newest and one starts at the oldest sample."
(let ((index (mod (+ (the int position) -1 *redline-index*) 400)))
(-> *redline-table* index)))
(define *blueline-table* (the-as (pointer float) (malloc 'debug 1600)))
(define *blueline-index* 0)
(defun float-save-blueline ((value float))
"Append value to the 400-sample blue debug plot, overwriting the oldest
sample when the ring wraps."
"Append value to the 400-sample blue debug
plot, overwriting the oldest sample when the ring wraps."
(set! (-> *blueline-table* *blueline-index*) value)
(set! *blueline-index* (+ *blueline-index* 1))
(when (>= *blueline-index* 400)
@@ -80,17 +70,18 @@
(none))
(defun float-lookup-blueline ((position float))
"Read the blue debug plot at position in its wrapped drawing order: zero is
newest and one starts at the oldest sample."
(let ((index (mod (+ (the int position) -1 *blueline-index*) 400))) (-> *blueline-table* index)))
"Read the blue debug plot at position in
its wrapped drawing order: zero is newest and one starts at the oldest sample."
(let ((index (mod (+ (the int position) -1 *blueline-index*) 400)))
(-> *blueline-table* index)))
(define *greenline-table* (the-as (pointer float) (malloc 'debug 1600)))
(define *greenline-index* 0)
(defun float-save-greenline ((value float))
"Append value to the 400-sample green debug plot, overwriting the oldest
sample when the ring wraps."
"Append value to the 400-sample green debug
plot, overwriting the oldest sample when the ring wraps."
(set! (-> *greenline-table* *greenline-index*) value)
(set! *greenline-index* (+ *greenline-index* 1))
(when (>= *greenline-index* 400)
@@ -99,17 +90,18 @@
(none))
(defun float-lookup-greenline ((position float))
"Read the green debug plot at position in its wrapped drawing order: zero is
newest and one starts at the oldest sample."
(let ((index (mod (+ (the int position) -1 *greenline-index*) 400))) (-> *greenline-table* index)))
"Read the green debug plot at position in
its wrapped drawing order: zero is newest and one starts at the oldest sample."
(let ((index (mod (+ (the int position) -1 *greenline-index*) 400)))
(-> *greenline-table* index)))
(define *yellowline-table* (the-as (pointer float) (malloc 'debug 1600)))
(define *yellowline-index* 0)
(defun float-save-yellowline ((value float))
"Append value to the 400-sample yellow debug plot, overwriting the oldest
sample when the ring wraps."
"Append value to the 400-sample yellow
debug plot, overwriting the oldest sample when the ring wraps."
(set! (-> *yellowline-table* *yellowline-index*) value)
(set! *yellowline-index* (+ *yellowline-index* 1))
(when (>= *yellowline-index* 400)
@@ -118,17 +110,18 @@
(none))
(defun float-lookup-yellowline ((position float))
"Read the yellow debug plot at position in its wrapped drawing order: zero is
newest and one starts at the oldest sample."
(let ((index (mod (+ (the int position) -1 *yellowline-index*) 400))) (-> *yellowline-table* index)))
"Read the yellow debug plot at position
in its wrapped drawing order: zero is newest and one starts at the oldest sample."
(let ((index (mod (+ (the int position) -1 *yellowline-index*) 400)))
(-> *yellowline-table* index)))
(define *timeplot-table* (the-as (pointer float) (malloc 'debug 1600)))
(define *timeplot-index* 0)
(defun float-save-timeplot ((value float))
"Append value to the 400-sample time debug plot, overwriting the oldest
sample when the ring wraps."
"Append value to the 400-sample time debug
plot, overwriting the oldest sample when the ring wraps."
(set! (-> *timeplot-table* *timeplot-index*) value)
(set! *timeplot-index* (+ *timeplot-index* 1))
(when (>= *timeplot-index* 400)
@@ -137,10 +130,9 @@
(none))
(defun float-lookup-timeplot ((position float))
"Read the time debug plot at position in its wrapped drawing order: zero is
newest and one starts at the oldest sample."
(let ((index (mod (+ (the int position) -1 *timeplot-index*) 400))) (-> *timeplot-table* index)))
"Read the time debug plot at position in
its wrapped drawing order: zero is newest and one starts at the oldest sample."
(let ((index (mod (+ (the int position) -1 *timeplot-index*) 400)))
(-> *timeplot-table* index)))
(define-perm *cam-layout* symbol #f)
0
File diff suppressed because it is too large Load Diff
@@ -4,15 +4,11 @@
(require "engine/camera/camera-h.gc")
(require "engine/math/matrix-h.gc")
;; NOTE - forward declaration needed for cam-interface
(define-extern *camera-dummy-vector* vector)
(define-extern *camera* camera-master) ;; unknown type
;; DECOMP BEGINS
;; Input gates shared by normal and debug camera states. Camera-layout and
;; object editors disable these while they own the controls.
(define *camera-read-analog* #t)
(define *camera-read-buttons* #t)
;; Allow the debug free camera's shoulder controls to move along camera z.
@@ -25,13 +21,10 @@
;; The persistent processes that coordinate camera selection and blend the
;; active camera behaviors.
(define-perm *camera* camera-master #f)
(define-perm *camera-combiner* camera-combiner #f)
;; Optional drawable followed by the debug orbit camera.
(define-perm *camera-orbit-target* (pointer process-drawable) #f)
(define-extern position-in-front-of-camera! (function vector float float vector))
;; TODO - forward declaration for weather-part
(define-extern matrix-local->world (function symbol symbol matrix))
+14 -10
View File
@@ -8,6 +8,8 @@
(require "engine/entity/entity-h.gc")
(require "engine/math/transformq-h.gc")
;; DECOMP BEGINS
(defun position-in-front-of-camera! ((out vector) (forward-distance float) (up-distance float))
"Place out at forward-distance along the camera's
forward axis and up-distance along its up axis, measured from the current camera translation."
@@ -20,7 +22,9 @@
"Return the camera local-to-world rotation. smooth? selects the
smoothed inverse-camera matrix; the second argument is retained for the shared interface but is
unused."
(if smooth? (-> *math-camera* inv-camera-rot-smooth) (-> *math-camera* inv-camera-rot)))
(if smooth?
(-> *math-camera* inv-camera-rot-smooth)
(-> *math-camera* inv-camera-rot)))
(defun matrix-world->local ()
"Return the current world-to-camera rotation matrix."
@@ -32,11 +36,13 @@
"Return the active camera position. Prefer the combiner output while a
camera transition is active, otherwise use the renderer camera, with a zero-vector fallback
before camera initialization."
(the-as vector
(cond
(*camera-combiner* (-> *camera-combiner* stack))
(*math-camera* (-> *math-camera* trans))
(else *camera-dummy-vector*))))
(cond
(*camera-combiner*
(-> *camera-combiner* trans))
(*math-camera*
(-> *math-camera* trans))
(else
*camera-dummy-vector*)))
(defun math-camera-pos ()
"Return the renderer's current camera translation."
@@ -50,11 +56,9 @@
(atan right-z right-x)))
(defbehavior camera-teleport-to-entity process ((start-entity entity-actor))
"Build a unit-scale camera transform from start-entity's
orientation and the position stored in the scale vector of its extra transform, then send it to
the camera master as an immediate teleport."
"Teleport the camera to the entity position."
(let ((teleport-transform (new 'stack 'transformq)))
(vector-copy! (-> teleport-transform trans) (-> (the-as transform (-> start-entity extra)) scale))
(vector-copy! (-> teleport-transform trans) (-> start-entity extra trans))
(quaternion-copy! (-> teleport-transform quat) (-> start-entity quat))
(vector-identity! (-> teleport-transform scale))
(send-event *camera* 'teleport-to-transformq teleport-transform))
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+37 -23
View File
@@ -22,13 +22,14 @@
(behavior ((proc process) (argc int) (message symbol) (block event-message-block))
(case message
(('teleport) #f)
(else (cam-standard-event-handler proc argc message block))))
(else
(cam-standard-event-handler proc argc message block))))
:enter
(behavior ()
(when (not (-> self enter-has-run))
(set! (-> self pivot-rad) 40960.0)
(set! (-> self blend-from-type) (the-as uint 1))
(set! (-> self blend-to-type) (the-as uint 1))))
(set! (-> self blend-from-type) (camera-blend-to-type slave-controlled))
(set! (-> self blend-to-type) (camera-blend-to-type slave-controlled))))
:code
(behavior ()
(loop
@@ -52,13 +53,14 @@
(+! (-> translation-delta z) (* 2.0 (-> *CAM_POINT_WATCH-bank* speed) left-y-input)))))
(let ((forward (new-stack-vector0)))
(let ((rotation-matrix (new-stack-matrix0)))
(matrix-axis-angle! rotation-matrix (the-as vector (-> self tracking)) (- (-> rotation-delta x)))
(matrix-axis-angle! rotation-matrix (-> self tracking inv-mat vector 0) (- (-> rotation-delta x)))
(vector-matrix*! forward (-> self tracking inv-mat vector 2) rotation-matrix)
(matrix-axis-angle! rotation-matrix (-> *camera* local-down) (- (-> rotation-delta y)))
(vector-matrix*! forward forward rotation-matrix))
(forward-down->inv-matrix (-> self tracking inv-mat) forward (-> *camera* local-down)))
(set! (-> self pivot-rad) (- (-> self pivot-rad) (-> translation-delta z)))
(if (< (-> self pivot-rad) 4096.0) (set! (-> self pivot-rad) 4096.0))
(if (< (-> self pivot-rad) 4096.0)
(set! (-> self pivot-rad) 4096.0))
(set-vector! translation-delta 0.0 0.0 (- (-> self pivot-rad)) 1.0)
(vector-matrix*! (-> self trans) translation-delta (-> self tracking inv-mat))))
(suspend)
@@ -276,8 +278,10 @@
Preserve the chosen up direction while yawing when one is supplied; otherwise allow unrestricted
yaw. Pitch and roll are then applied in camera-local axes before the local translation is rotated
into world space. Return false when the controller is invalid or menus own the camera."
(if (logtest? (-> *cpad-list* cpads controller-index valid) 128) (return (the-as vector #f)))
(if (= *master-mode* 'menu) (return (the-as vector #f)))
(if (logtest? (-> *cpad-list* cpads controller-index valid) 128)
(return (the-as vector #f)))
(if (= *master-mode* 'menu)
(return (the-as vector #f)))
(let ((move-info (new 'stack 'camera-free-floating-move-info)))
(cam-free-floating-input (-> move-info rv) (-> move-info tv) (not up) controller-index)
(cond
@@ -309,18 +313,20 @@
(behavior ((proc process) (argc int) (message symbol) (block event-message-block))
(case message
(('teleport) #f)
(else (cam-standard-event-handler proc argc message block))))
(else
(cam-standard-event-handler proc argc message block))))
:enter
(behavior ()
(when (not (-> self enter-has-run))
(set! (-> self blend-from-type) (the-as uint 1))
(set! (-> self blend-to-type) (the-as uint 1))
(set! (-> self blend-from-type) (camera-blend-to-type slave-controlled))
(set! (-> self blend-to-type) (camera-blend-to-type slave-controlled))
(send-event *camera-combiner* 'stop-tracking)))
:code
(behavior ()
(loop
(let ((up (-> *camera* local-down)))
(if (logtest? (-> self options) 8) (set! up (the-as vector #f)))
(if (logtest? (-> self options) (cam-slave-options ALLOW_Z_ROT))
(set! up (the-as vector #f)))
(cam-free-floating-move (-> self tracking inv-mat) (-> self trans) up (the-as int (-> *CAMERA-bank* joypad))))
(suspend))))
@@ -331,12 +337,14 @@
(orbit-off vector :inline)
(radius-lerp float)))
(deftype CAM_ORBIT-bank (basic)
((RADIUS_MAX float)
(RADIUS_MIN float)
(TARGET_OFF_ADJUST float)
(ORBIT_OFF_ADJUST float)))
(define *CAM_ORBIT-bank*
(new 'static 'CAM_ORBIT-bank :RADIUS_MAX 61440.0 :RADIUS_MIN 409.6 :TARGET_OFF_ADJUST 81.92 :ORBIT_OFF_ADJUST 81.92))
@@ -359,23 +367,26 @@
(behavior ((proc process) (argc int) (message symbol) (block event-message-block))
(case message
(('teleport) #f)
(else (cam-standard-event-handler proc argc message block))))
(else
(cam-standard-event-handler proc argc message block))))
:enter
(behavior ()
(when (not (-> self enter-has-run))
(if (not *camera-orbit-target*) (cam-slave-go cam-free-floating))
(if (not *camera-orbit-target*)
(cam-slave-go cam-free-floating))
(let ((target-to-camera (new-stack-vector0)))
(vector-! target-to-camera (-> self trans) (-> *camera-orbit-target* 0 root trans))
(set! (-> *camera-orbit-info* rot) (atan (-> target-to-camera x) (-> target-to-camera z))))
(set! (-> self blend-from-type) (the-as uint 1))
(set! (-> self blend-to-type) (the-as uint 1))))
(set! (-> self blend-from-type) (camera-blend-to-type slave-controlled))
(set! (-> self blend-to-type) (camera-blend-to-type slave-controlled))))
:exit
(behavior ()
'())
:code
(behavior ()
(loop
(if (not *camera-orbit-target*) (cam-slave-go cam-free-floating))
(if (not *camera-orbit-target*)
(cam-slave-go cam-free-floating))
(when *camera-read-analog*
(let ((zoom-input (analog-input (the-as int (-> *cpad-list* cpads 0 righty)) 128.0 32.0 110.0 0.05)))
(cond
@@ -383,20 +394,23 @@
(+! (-> *camera-orbit-info* radius-lerp) (* 0.05 (- 1.0 (-> *camera-orbit-info* radius-lerp)))))
((< zoom-input (* 0.05 (- (-> *camera-orbit-info* radius-lerp))))
(+! (-> *camera-orbit-info* radius-lerp) (* 0.05 (- (-> *camera-orbit-info* radius-lerp)))))
(else (+! (-> *camera-orbit-info* radius-lerp) zoom-input))))
(else
(+! (-> *camera-orbit-info* radius-lerp) zoom-input))))
(set! (-> *camera-orbit-info* radius)
(lerp (-> *CAM_ORBIT-bank* RADIUS_MIN) (-> *CAM_ORBIT-bank* RADIUS_MAX) (-> *camera-orbit-info* radius-lerp))))
(cond
((cpad-hold? 0 l2)
(if (cpad-hold? 0 l1)
(set! (-> *camera-orbit-info* target-off y)
(- (-> *camera-orbit-info* target-off y) (-> *CAM_ORBIT-bank* TARGET_OFF_ADJUST))))
(if (cpad-hold? 0 r1) (+! (-> *camera-orbit-info* target-off y) (-> *CAM_ORBIT-bank* TARGET_OFF_ADJUST))))
(set! (-> *camera-orbit-info* target-off y)
(- (-> *camera-orbit-info* target-off y) (-> *CAM_ORBIT-bank* TARGET_OFF_ADJUST))))
(if (cpad-hold? 0 r1)
(+! (-> *camera-orbit-info* target-off y) (-> *CAM_ORBIT-bank* TARGET_OFF_ADJUST))))
(else
(if (cpad-hold? 0 l1)
(set! (-> *camera-orbit-info* orbit-off y)
(- (-> *camera-orbit-info* orbit-off y) (-> *CAM_ORBIT-bank* ORBIT_OFF_ADJUST))))
(if (cpad-hold? 0 r1) (+! (-> *camera-orbit-info* orbit-off y) (-> *CAM_ORBIT-bank* ORBIT_OFF_ADJUST)))))
(set! (-> *camera-orbit-info* orbit-off y)
(- (-> *camera-orbit-info* orbit-off y) (-> *CAM_ORBIT-bank* ORBIT_OFF_ADJUST))))
(if (cpad-hold? 0 r1)
(+! (-> *camera-orbit-info* orbit-off y) (-> *CAM_ORBIT-bank* ORBIT_OFF_ADJUST)))))
(when *camera-read-analog*
(let ((orbit-input (analog-input (the-as int (-> *cpad-list* cpads 0 rightx)) 128.0 32.0 110.0 (* 21845.334 (seconds-per-frame)))))
(set! (-> *camera-orbit-info* rot) (the float (sar (shl (the int (+ (-> *camera-orbit-info* rot) orbit-input)) 48) 48)))))
File diff suppressed because it is too large Load Diff
+1 -8
View File
@@ -9,6 +9,7 @@
:bitfield #t
(allow-z 0))
;; DECOMP BEGINS
(define *external-cam-options* (external-cam-option))
;; False for the gameplay camera, or the controller/debug mode that directly
@@ -23,17 +24,9 @@
;; Alternate field of view, position, inverse rotation, and debug target used
;; while *camera-look-through-other* is active.
(define-perm *camera-other-fov* bfloat (new 'static 'bfloat :data 11650.845))
(define-perm *camera-other-trans* vector (vector-reset! (new 'global 'vector)))
(define-perm *camera-other-matrix* matrix (matrix-identity! (new 'global 'matrix)))
;; Vertical camera impulse shared by the gameplay and alternate-camera paths.
(define-perm *camera-smush-control* smush-control (set-zero! (new 'global 'smush-control)))
(define-perm *camera-other-root* vector (vector-reset! (new 'global 'vector)))
;; TODO - actually defined in cam-states-dbg
(define-extern cam-free-floating-move (function matrix vector vector int vector))
(define-extern cam-free-floating-input (function vector vector symbol int vector))
+42 -37
View File
@@ -36,10 +36,7 @@
(defun set-point ((point vector) (x float) (y float) (z float))
"Set point's xyz coordinates and set w to one."
(set! (-> point x) x)
(set! (-> point y) y)
(set! (-> point z) z)
(set! (-> point w) 1.0)
(set-vector! point x y z 1.0)
(none))
(defun update-view-planes ((camera math-camera) (planes (inline-array plane)) (scale float))
@@ -78,8 +75,7 @@
(far-bottom-left-ray (new-stack-vector0))
(far-bottom-right-ray (new-stack-vector0)))
(set! (-> (new 'stack-no-clear 'vector) quad) (the-as uint128 0))
(let ((camera-position (new 'stack-no-clear 'vector)))
(set! (-> camera-position quad) (the-as uint128 0))
(let ((camera-position (new-stack-vector0)))
(set! (-> camera-position quad) (-> camera inv-camera-rot vector 3 quad))
(vector-! far-top-left-ray (-> frustum yon-top-left) camera-position)
(vector-! far-top-right-ray (-> frustum yon-top-right) camera-position)
@@ -136,22 +132,26 @@
(set! use-adjacent? (logtest? (vis-info-flag using-this-as-only-vis) (-> adjacent-vis flags)))
(if (< (-> adjacent-vis length) (-> adjacent-vis from-bsp current-leaf-idx)) (set! use-adjacent? #f)))
use-self?))
(if (!= (-> active-level all-visible?) 'loading) (set! (-> active-level all-visible?) #f))
(if (!= (-> active-level all-visible?) 'loading)
(set! (-> active-level all-visible?) #f))
(when (update-vis! active-level self-vis (-> self-vis ramdisk) (-> self-vis string-block))
;; A successful update makes every other cached string stale.
(countdown (i 8)
(let ((vis-info (-> active-level vis-info i)))
(when vis-info
(if (!= vis-info self-vis) (set! (-> vis-info current-vis-string) (the-as uint -1))))))
(if (!= vis-info self-vis)
(set! (-> vis-info current-vis-string) (the-as uint -1))))))
(set! (-> active-level all-visible?) #f)))
(use-adjacent?
(if (!= (-> active-level all-visible?) 'loading) (set! (-> active-level all-visible?) #f))
(if (!= (-> active-level all-visible?) 'loading)
(set! (-> active-level all-visible?) #f))
(when (update-vis! active-level adjacent-vis (-> adjacent-vis ramdisk) (-> adjacent-vis string-block))
;; The adjacent string follows the same cache rules.
(countdown (i 8)
(let ((vis-info (-> active-level vis-info i)))
(when vis-info
(if (!= vis-info adjacent-vis) (set! (-> vis-info current-vis-string) (the-as uint -1))))))
(if (!= vis-info adjacent-vis)
(set! (-> vis-info current-vis-string) (the-as uint -1))))))
(set! (-> active-level all-visible?) #f)))
;; Keep the old visibility bits while the next string loads
;; during play, avoiding an all-visible flash between strings.
@@ -176,14 +176,18 @@
(controller-index 0))
(cond
((= mode 'locked) (set! mode #f))
((= mode 'pad-1) (set! controller-index 1))
((not *camera-combiner*) (set! mode 'pad-0)))
((= mode 'pad-1)
(set! controller-index 1))
((not *camera-combiner*)
(set! mode 'pad-0)))
(when mode
;; Gravity supplies the camera's down direction. Passing #f for up
;; allows a fully free orientation, including roll.
(let ((up (vector-negate-in-place! (vector-normalize-copy! (new-stack-vector0) (-> *standard-dynamics* gravity) 1.0))))
(if (= (vector-length up) 0.0) (set! (-> up y) -1.0))
(if (logtest? *external-cam-options* (external-cam-option allow-z)) (set! up (the-as vector #f)))
(if (= (vector-length up) 0.0)
(set! (-> up y) -1.0))
(if (logtest? *external-cam-options* (external-cam-option allow-z))
(set! up (the-as vector #f)))
(cam-free-floating-move *save-camera-inv-rot* (-> camera trans) up controller-index))))
(matrix-copy! (-> *math-camera* inv-camera-rot) *save-camera-inv-rot*)
camera)
@@ -242,7 +246,8 @@
(-> *target* control trans z))
(format #t "Dist = ~F~%" (* 0.00024414062 (vector-vector-xz-distance (-> *target* control trans) *start-pos*)))
(set! *start-timer* (the-as int #f)))
(if (< 179 *timer-value*) (format *stdcon* "~%~%Time = ~D~%" *timer-value*))
(if (< 179 *timer-value*)
(format *stdcon* "~%~%Time = ~D~%" *timer-value*))
(set! *timer-value* (+ *timer-value* 1)))
(when (not *start-timer*)
(set! *timer-value* 0)
@@ -272,13 +277,14 @@
(update! *camera-smush-control*)
(cond
((or (= *master-mode* 'pause) (= *master-mode* 'progress) *progress-process*))
((>= *camera-look-through-other* 2) (set! *camera-look-through-other* 1))
((and (= *camera-look-through-other* 1) (!= *master-mode* 'menu)) (set! *camera-look-through-other* 0) 0))
;; Priority is external control, the alternate/debug camera, the gameplay
;; combiner, then the controller fallback. Alternate and gameplay poses
;; also refresh the saved external orientation to avoid a jump on entry.
((>= *camera-look-through-other* 2)
(set! *camera-look-through-other* 1))
((and (= *camera-look-through-other* 1) (!= *master-mode* 'menu))
(set! *camera-look-through-other* 0)
0))
(cond
(*external-cam-mode* (move-camera-from-pad *math-camera*))
(*external-cam-mode*
(move-camera-from-pad *math-camera*))
((nonzero? *camera-look-through-other*)
(set! (-> *math-camera* fov) (-> *camera-other-fov* data))
(vector-copy! (-> *math-camera* trans) *camera-other-trans*)
@@ -297,14 +303,15 @@
;; reduce the mip factor so zoomed views do not choose overly coarse mips;
;; wider views are capped at one.
(cond
(*camera-no-mip-correction* (set! (-> *math-camera* fov-correction-factor) 1.0))
(*camera-no-mip-correction*
(set! (-> *math-camera* fov-correction-factor) 1.0))
(else
(let ((mip-fov (fmin 11650.845 (-> *math-camera* fov))))
(set! (-> *math-camera* fov-correction-factor) (* 0.00008583069 mip-fov)))))
;; Blend from the saved orientation toward the current pose while smooth-t
;; decays. Once complete, keep an exact copy of the current orientation.
(if (< 0.0 (-> *math-camera* smooth-t))
(set! (-> *math-camera* smooth-t) (- (-> *math-camera* smooth-t) (-> *math-camera* smooth-step))))
(set! (-> *math-camera* smooth-t) (- (-> *math-camera* smooth-t) (-> *math-camera* smooth-step))))
(cond
((< 0.0 (-> *math-camera* smooth-t))
(let ((smooth-rotation (new-stack-quaternion0)))
@@ -317,11 +324,9 @@
(else
(matrix-copy! (-> *math-camera* inv-camera-rot-smooth) (-> *math-camera* inv-camera-rot))))
(if (and (!= *master-mode* 'menu) *display-camera-info*)
(format *stdcon* "cam pos ~M ~M ~M~%" (-> *math-camera* trans x) (-> *math-camera* trans y) (-> *math-camera* trans z)))
;; Preserve the old view-projection before rebuilding it. A reset instead
;; copies the new matrix afterward, suppressing one frame of camera motion.
(when (zero? (-> *math-camera* reset))
(matrix-copy! (-> *math-camera* prev-camera-temp) (-> *math-camera* camera-temp)))
(format *stdcon* "cam pos ~M ~M ~M~%" (-> *math-camera* trans x) (-> *math-camera* trans y) (-> *math-camera* trans z)))
(if (zero? (-> *math-camera* reset))
(matrix-copy! (-> *math-camera* prev-camera-temp) (-> *math-camera* camera-temp)))
(let ((view-projection (-> *math-camera* camera-temp))
(view-matrix (-> *math-camera* camera-rot))
(inverse-view-matrix (-> *math-camera* inv-camera-rot))
@@ -329,10 +334,11 @@
;; Rigid inverse translation is -C transformed by the transposed
;; orientation. The inverse view keeps C directly in its fourth row.
(let ((negative-camera-position (new-stack-vector0)))
(set! (-> negative-camera-position x) (- (-> camera-position x)))
(set! (-> negative-camera-position y) (- (-> camera-position y)))
(set! (-> negative-camera-position z) (- (-> camera-position z)))
(set! (-> negative-camera-position w) 1.0)
(set-vector! negative-camera-position
(- (-> camera-position x))
(- (-> camera-position y))
(- (-> camera-position z))
1.0)
(vector-matrix*! negative-camera-position negative-camera-position view-matrix)
(set! (-> view-matrix vector 3 quad) (-> negative-camera-position quad)))
(matrix*! view-projection view-matrix (-> *math-camera* perspective))
@@ -350,7 +356,7 @@
(set! (-> *instance-tie-work* hmge-d y) fog-max)
(set! (-> *instance-tie-work* hmge-d z) (* 32.0 near-distance))
(set! (-> *instance-tie-work* hmge-d w) (* near-distance (-> *math-camera* hmge-scale w)))
(let ((hvdf-offset (-> *math-camera* hvdf-off quad))) (set! (-> *instance-tie-work* hvdf-offset quad) hvdf-offset))
(vector-copy! (-> *instance-tie-work* hvdf-offset) (-> *math-camera* hvdf-off))
(set! (-> *instance-shrub-work* hmge-d x) fog-min)
(set! (-> *instance-shrub-work* hmge-d y) fog-max)
(set! (-> *instance-shrub-work* hmge-d z) (* 3.0 near-distance))
@@ -362,9 +368,7 @@
(set! (-> *instance-shrub-work* billboard-const z) fog-min)
(set! (-> *instance-shrub-work* billboard-const w) fog-max))
(set! (-> *instance-shrub-work* constants w) (the-as float (-> *math-camera* vis-gifs 0 fog0)))
(let ((hvdf-offset (-> *math-camera* hvdf-off quad))) (set! (-> *instance-shrub-work* hvdf-offset quad) hvdf-offset))
;; The ordinary side planes cull the view frustum. The four-times-wider
;; guard planes give TIE and shrub generation room around the visible area.
(vector-copy! (-> *instance-shrub-work* hvdf-offset) (-> *math-camera* hvdf-off))
(update-view-planes *math-camera* (-> *math-camera* plane) 1.0)
(update-view-planes *math-camera* (-> *math-camera* guard-plane) 4.0)
(vector-copy! (-> *instance-shrub-work* guard-plane 0) (-> *math-camera* guard-plane 0))
@@ -376,5 +380,6 @@
(vector-copy! (-> *instance-tie-work* guard-plane 2) (-> *math-camera* guard-plane 2))
(vector-copy! (-> *instance-tie-work* guard-plane 3) (-> *math-camera* guard-plane 3))
(update-visible *math-camera*)
(if (not (paused?)) (update-wind *wind-work* *wind-scales*))
(if (not (paused?))
(update-wind *wind-work* *wind-scales*))
#f)
+92 -65
View File
@@ -4,35 +4,6 @@
(require "engine/math/vector-h.gc")
(require "engine/gfx/hw/display-h.gc")
;; TODO - for cam-layout
(define-extern v-slrp2! (function vector vector vector float vector float vector))
(define-extern v-slrp3! (function vector vector vector vector float vector))
(declare-type camera-slave process)
(declare-type camera-master process)
(declare-type tracking-point structure)
(declare-type cam-rotation-tracker structure)
(declare-type camera-combiner process)
;; TODO - for cam-master
;; TODO - for camera
(define-extern camera-line-rel-len (function vector vector float vector4w none))
(define-extern cam-calc-follow! (function cam-rotation-tracker vector symbol vector))
(define-extern slave-set-rotation! (function cam-rotation-tracker vector float float symbol none))
;; TODO - for cam-combiner
(define-extern paused? (function symbol))
;; TODO - for cam-start
(define-extern cam-master-init (function none :behavior camera-master))
(defenum cam-slave-options
:bitfield #t
(BUTT_CAM)
@@ -54,6 +25,28 @@
(STICKY_ANGLE)
(AIR_EXIT))
(defenum cam-slave-options-i
:bitfield #t
:type int32
(BUTT_CAM)
(SAME_SIDE)
(MOVE_SPHERICAL)
(ALLOW_Z_ROT)
(JUMP_PITCHES)
(COLLIDE)
(FIND_HIDDEN_TARGET)
(DRAG)
(PLAYER_MOVING_CAMERA)
(LINE_OF_SIGHT)
(MOVEMENT_BLOCKED)
(SHRINK_MAX_ANGLE)
(GOTO_GOOD_POINT)
(BLOCK_SHIFT_BUTTONS)
(BIKE_MODE)
(NO_ROTATE)
(STICKY_ANGLE)
(AIR_EXIT))
(defenum cam-index-options
:type uint32
:bitfield #t
@@ -67,6 +60,31 @@
(ccw 2)
(between 3))
(defenum cam-track-status
:type uint64
(use-slave-tracking 0)
(track-at-combiner 1)
(track-at-dst 2)
(track-at-src 3))
(defenum camera-blend-to-type
:type uint64
(direct 0)
(slave-controlled 1)
(combiner-tracked 2))
(defenum cam-master-options
:type uint32
:bitfield #t
(ignore-regions 0)
(have-target 1)
(switch-only-on-ground 2)
(set-combiner-axis 3)
(flip-combiner 4)
(have-ease-to-pos 5)
(in-base-region 6))
;; DECOMP BEGINS
;; Shared gameplay-camera tuning used for collision movement, input response,
@@ -147,17 +165,15 @@
(advance-used-point! (_type_ tracking-spline-sampler) none)
(prune-most-collinear! (_type_) none)
(prune-shallow-points! (_type_ float) none)
(add-point! (_type_ vector float float symbol) int)
(add-point! (_type_ vector meters meters symbol) int)
(accumulate-sample! (_type_ float vector tracking-spline-sampler) vector)
(sample-point! (_type_ float vector tracking-spline-sampler) vector)
(apply-trail-correction! (_type_ vector int) none)
(follow-update! (_type_ vector float float) vector)
(trim-to-length! (_type_ float) none)
(follow-update! (_type_ vector meters meters) vector)
(trim-to-length! (_type_ meters) none)
(debug-draw (_type_) none)))
;; A scalar spring-like seeker. value accelerates toward target and its speed
;; is limited by both max-vel and max-partial times the remaining distance, so
;; it eases down automatically near the target.
(deftype cam-float-seeker (structure)
((target float)
(value float)
@@ -173,8 +189,8 @@
(jump-to-target! (_type_ float) float)))
(defmethod init-cam-float-seeker ((this cam-float-seeker) (initial-value float) (accel float) (max-vel float) (max-partial float))
"Initialize target and value to initial-value, clear velocity, and set the
acceleration and two speed limits."
"Initialize target and value to initial-value, clear
velocity, and set the acceleration and two speed limits."
(set! (-> this target) initial-value)
(set! (-> this value) initial-value)
(set! (-> this vel) 0.0)
@@ -196,24 +212,27 @@
(none))
(defmethod update! ((this cam-float-seeker) (offset float))
"Advance one frame toward target plus offset. Acceleration and displacement
use the display time ratio, and velocity is capped by the smaller of max-vel
and max-partial times the remaining distance."
"Advance one frame toward target plus offset. Acceleration and
displacement use the display time ratio, and velocity is capped by the
smaller of max-vel and max-partial times the remaining distance."
0.0
0.0
(let* ((pos-error (- (+ (-> this target) offset) (-> this value)))
(partial-velocity-limit (* (-> this max-partial) (fabs pos-error))))
(let ((daccel (* pos-error (* (-> this accel) (-> *display* time-adjust-ratio))))) (+! (-> this vel) daccel))
(let ((daccel (* pos-error (* (-> this accel) (-> *display* time-adjust-ratio)))))
(+! (-> this vel) daccel))
(let ((abs-vel (fabs (-> this vel)))
(abs-vel-limit (fmin partial-velocity-limit (-> this max-vel))))
(if (< abs-vel-limit abs-vel) (set! (-> this vel) (* (-> this vel) (/ abs-vel-limit abs-vel))))))
(let ((dpos (* (-> this vel) (-> *display* time-adjust-ratio)))) (+! (-> this value) dpos))
(if (< abs-vel-limit abs-vel)
(set! (-> this vel) (* (-> this vel) (/ abs-vel-limit abs-vel))))))
(let ((dpos (* (-> this vel) (-> *display* time-adjust-ratio))))
(+! (-> this value) dpos))
0
(none))
(defmethod jump-to-target! ((this cam-float-seeker) (offset float))
"Set value directly to target plus offset, clear velocity, and return the new
value."
"Set value directly to target plus offset, clear velocity,
and return the new value."
(set! (-> this value) (+ (-> this target) offset))
(set! (-> this vel) 0.0))
@@ -231,11 +250,15 @@
(update! (_type_ vector) none)))
(defmethod init! ((this cam-vector-seeker) (initial-value vector) (accel float) (max-vel float) (max-partial float))
"Initialize target and value from initial-value, or zero when it is false;
clear velocity and set the acceleration and speed limits."
"Initialize target and value from initial-value, or zero when it is
false; clear velocity and set the acceleration and speed limits."
(cond
(initial-value (vector-copy! (-> this target) initial-value) (vector-copy! (-> this value) initial-value))
(else (vector-reset! (-> this target)) (vector-reset! (-> this value))))
(initial-value
(vector-copy! (-> this target) initial-value)
(vector-copy! (-> this value) initial-value))
(else
(vector-reset! (-> this target))
(vector-reset! (-> this value))))
(vector-reset! (-> this vel))
(set! (-> this accel) accel)
(set! (-> this max-vel) max-vel)
@@ -244,19 +267,23 @@
(none))
(defmethod update! ((this cam-vector-seeker) (offset vector))
"Advance one frame toward target plus optional offset, limiting velocity
magnitude by max-vel and the remaining-distance limit."
"Advance one frame toward target plus optional offset, limiting
velocity magnitude by max-vel and the remaining-distance limit."
(let ((error (new 'stack-no-clear 'vector)))
0.0
(cond
(offset (vector+! error (-> this target) offset) (vector-! error error (-> this value)))
(else (vector-! error (-> this target) (-> this value))))
(offset
(vector+! error (-> this target) offset)
(vector-! error error (-> this value)))
(else
(vector-! error (-> this target) (-> this value))))
(let ((partial-velocity-limit (* (-> this max-partial) (vector-length error))))
(vector-float*! error error (* (-> this accel) (-> *display* time-adjust-ratio)))
(vector+! (-> this vel) (-> this vel) error)
(let ((velocity (vector-length (-> this vel)))
(velocity-limit (fmin partial-velocity-limit (-> this max-vel))))
(if (< velocity-limit velocity) (vector-float*! (-> this vel) (-> this vel) (/ velocity-limit velocity)))))
(if (< velocity-limit velocity)
(vector-float*! (-> this vel) (-> this vel) (/ velocity-limit velocity)))))
(vector-float*! error (-> this vel) (-> *display* time-adjust-ratio))
(vector+! (-> this value) (-> this value) error))
0
@@ -286,8 +313,8 @@
(dist-from-dest float)
(flip-control-axis vector :inline)
(velocity vector :inline)
(tracking-status uint64)
(tracking-options int32)
(tracking-status cam-track-status)
(tracking-options cam-slave-options-i)
(tracking cam-rotation-tracker :inline))
(:states
cam-combiner-active))
@@ -296,9 +323,9 @@
;; slave alive together while the combiner transitions between them.
(deftype camera-slave (process)
((trans vector :inline)
(fov float)
(fov0 float)
(fov1 float)
(fov degrees)
(fov0 degrees)
(fov1 degrees)
(fov-index cam-index :inline)
(tracking cam-rotation-tracker :inline)
(view-off-param float)
@@ -314,8 +341,8 @@
(circular-follow vector :inline)
(max-angle-offset float)
(max-angle-curr float)
(options uint32)
(cam-entity entity)
(options cam-slave-options)
(cam-entity entity-camera)
(velocity vector :inline)
(desired-pos vector :inline)
(time-dist-too-far uint32)
@@ -338,8 +365,8 @@
(spline-follow-dist float)
(change-event-from (pointer process-drawable))
(enter-has-run symbol)
(blend-from-type uint64)
(blend-to-type uint64)
(blend-from-type camera-blend-to-type)
(blend-to-type camera-blend-to-type)
(have-phony-joystick basic)
(phony-joystick-x float)
(phony-joystick-y float)
@@ -378,10 +405,10 @@
;; active slaves, target transforms and tracking trail, and transition state;
;; the combiner produces the final rendered camera.
(deftype camera-master (process)
((master-options uint32)
((master-options cam-master-options)
(num-slaves int32)
(slave (pointer camera-slave) 2)
(slave-options uint32)
(slave-options cam-slave-options)
(view-off-param-save float)
(changer uint32)
(cam-entity entity)
+278 -210
View File
@@ -16,15 +16,18 @@
(define *cam-res-string* (new 'global 'string 64 (the-as string #f)))
(defun cam-slave-get-vector-with-offset ((source-actor entity-actor) (out vector) (prop-name symbol))
(defun cam-slave-get-vector-with-offset ((source-actor entity-camera) (out vector) (prop-name symbol))
"Read property from actor, using its live
translation or rotation for the matching property names, add an optional property-offset vector,
and write out. Return true when a value was available."
(local-vars (base-value structure))
(cond
((= prop-name 'trans) (set! base-value (-> source-actor trans)))
((= prop-name 'rot) (set! base-value (-> source-actor quat)))
(else (set! base-value (res-lump-struct source-actor prop-name structure))))
((= prop-name 'trans)
(set! base-value (-> source-actor trans)))
((= prop-name 'rot)
(set! base-value (-> source-actor quat)))
(else
(set! base-value (res-lump-struct source-actor prop-name structure))))
(let ((struct-getter (method-of-type res-lump get-property-struct)))
(format (clear *res-key-string*) "~S~S" prop-name '-offset)
(let ((offset-value (struct-getter source-actor
@@ -35,8 +38,12 @@
(the-as (pointer res-tag) #f)
*res-static-buf*)))
(cond
((and base-value offset-value) (vector+! out (the-as vector base-value) (the-as vector offset-value)) #t)
((the-as vector base-value) (vector-copy! out (the-as vector base-value)) #t)
((and base-value offset-value)
(vector+! out (the-as vector base-value) (the-as vector offset-value))
#t)
((the-as vector base-value)
(set! (-> out quad) (-> (the-as vector base-value) quad))
#t)
(else #f)))))
(defun cam-slave-get-flags ((source-entity entity) (prop-name symbol))
@@ -62,7 +69,7 @@
(the-as uint128 0)
(the-as (pointer res-tag) #f)
*res-static-buf*)))
(logclear (logior base-flags set-flags) clear-flags)))))
(the-as cam-slave-options (logclear (logior base-flags set-flags) clear-flags))))))
(defun cam-slave-get-float ((source-entity entity) (prop-name symbol) (default-value float))
"Read property from entity with default-value, add the
@@ -92,7 +99,9 @@
0.0
(the-as (pointer res-tag) #f)
*res-static-buf*)))
(if (= base-fov 0.0) (+ 11650.845 fov-offset) (+ base-fov fov-offset)))))
(if (= base-fov 0.0)
(+ 11650.845 fov-offset)
(+ base-fov fov-offset)))))
(defun cam-slave-get-intro-step ((source-entity entity))
"Read intro-time plus intro-time-offset and return the
@@ -108,7 +117,9 @@
0.0
(the-as (pointer res-tag) #f)
*res-static-buf*))))
(if (>= 0.0 duration) 0.004166667 (/ 0.016666668 duration)))))
(if (>= 0.0 duration)
0.004166667
(/ 0.016666668 duration)))))
(defun cam-slave-get-interp-time ((source-entity entity))
"Read interpTime plus interpTime-offset from entity and
@@ -124,12 +135,12 @@
0.0
(the-as (pointer res-tag) #f)
*res-static-buf*))))
(if (>= 0.001 duration) (set! duration 0.0))
(if (>= 0.001 duration)
(set! duration 0.0))
duration)))
(defun cam-slave-get-rot ((source-actor entity-actor) (out-matrix matrix))
"Convert actor's rotation to out-matrix after composing an optional
rot-offset quaternion."
(defun cam-slave-get-rot ((source-actor entity-camera) (out-matrix matrix))
"Get the rotation of the entity, including optional rotation offset."
(let ((struct-getter (method-of-type res-lump get-property-struct))
(source-copy source-actor))
(format (clear *res-key-string*) "~S~S" 'rot '-offset)
@@ -146,7 +157,8 @@
(quaternion*! combined-rotation (the-as quaternion rotation-offset) (-> source-actor quat))
(quaternion-normalize! combined-rotation)
(quaternion->matrix out-matrix combined-rotation)))
(else (quaternion->matrix out-matrix (-> source-actor quat))))))
(else
(quaternion->matrix out-matrix (-> source-actor quat))))))
out-matrix)
(defun cam-state-from-entity ((source-entity entity))
@@ -156,12 +168,16 @@
(let ((camera-path (new 'stack 'curve)))
(the-as state
(cond
((not source-entity) (the-as (state camera-slave) #f))
((not source-entity)
(the-as (state camera-slave) #f))
((res-lump-struct source-entity 'pivot structure) cam-circular)
((res-lump-struct source-entity 'align structure) cam-standoff-read-entity)
((res-lump-struct source-entity 'align structure)
cam-standoff-read-entity)
((get-curve-data! source-entity camera-path 'campath 'campath-k -1000000000.0) cam-spline)
((< 0.0 (cam-slave-get-float source-entity 'stringMaxLength 0.0)) *camera-base-mode*)
(else cam-fixed-read-entity)))))
((< 0.0 (cam-slave-get-float source-entity 'stringMaxLength 0.0))
*camera-base-mode*)
(else
cam-fixed-read-entity)))))
(defun parameter-ease-none ((value object))
"Return value unchanged."
@@ -181,8 +197,10 @@
((>= t 1.0) 1.0)
((>= 0.0 t) 0.0)
((>= 0.25 t) (/ t 2))
((>= t 0.75) (- 1.0 (* 0.5 (- 1.0 t))))
(else (+ 0.125 (* 1.5 (+ -0.25 t))))))
((>= t 0.75)
(- 1.0 (* 0.5 (- 1.0 t))))
(else
(+ 0.125 (* 1.5 (+ -0.25 t))))))
(defun parameter-ease-sqrt-clamp ((t float))
"Clamp t to 0..1 and apply the symmetric square-root
@@ -190,8 +208,10 @@
(cond
((>= t 1.0) 1.0)
((>= 0.0 t) 0.0)
((>= 0.5 t) (* 0.5 (- 1.0 (sqrtf (- 1.0 (* 2.0 t))))))
(else (* 0.5 (+ 1.0 (sqrtf (+ -1.0 (* 2.0 t))))))))
((>= 0.5 t)
(* 0.5 (- 1.0 (sqrtf (- 1.0 (* 2.0 t))))))
(else
(* 0.5 (+ 1.0 (sqrtf (+ -1.0 (* 2.0 t))))))))
(defun fourth-power ((x float))
"Return x to the fourth power."
@@ -207,8 +227,10 @@
(cond
((>= t 1.0) 1.0)
((>= 0.0 t) 0.0)
((>= 0.5 t) (* 0.5 (square (* 2.0 t))))
(else (- 1.0 (* 0.5 (square (* 2.0 (- 1.0 t))))))))
((>= 0.5 t)
(* 0.5 (square (* 2.0 t))))
(else
(- 1.0 (* 0.5 (square (* 2.0 (- 1.0 t))))))))
(defun parameter-ease-sin-clamp ((t float))
"Clamp t to 0..1 and apply a half-cosine ease with zero
@@ -216,7 +238,8 @@
(cond
((>= t 1.0) 1.0)
((>= 0.0 t) 0.0)
(else (+ 0.5 (* 0.5 (sin (* 182.04445 (+ -90.0 (* 180.0 t)))))))))
(else
(+ 0.5 (* 0.5 (sin (* 182.04445 (+ -90.0 (* 180.0 t)))))))))
(defmethod setup-from-entity! ((this cam-index) (prop-name symbol) (source-entity entity) (cam-pos vector) (fallback-curve curve))
"Read the two endpoint vectors from entity data or
@@ -314,7 +337,11 @@
(set! (-> this sample-len) 0.0)
(set! (-> this used-count) 1)
(vector-copy! (-> this old-position) start-pos)
(let ((i 1)) (while (!= i 31) (set! (-> this point i next) (+ i 1)) (+! i 1)) (set! (-> this point i next) -134250495))
(let ((i 1))
(while (!= i 31)
(set! (-> this point i next) (+ i 1))
(+! i 1))
(set! (-> this point i next) -134250495))
0
(none))
@@ -350,7 +377,8 @@
(set! (-> this partial-point) (-> sampler partial-pt))
(when (= (-> this next-to-last-point) cur-pt)
(set! (-> this summed-len) (-> this point cur-pt tp-length))
(if (= (-> sampler cur-pt) (-> this end-point)) (set! (-> this partial-point) 0.99999)))
(if (= (-> sampler cur-pt) (-> this end-point))
(set! (-> this partial-point) 0.99999)))
(when (!= (-> sampler cur-pt) cur-pt)
(while (and (!= (-> this point cur-pt next) (-> sampler cur-pt)) (!= (-> this point cur-pt next) (-> this next-to-last-point)))
(set! (-> this summed-len) (- (-> this summed-len) (-> this point cur-pt tp-length)))
@@ -364,7 +392,9 @@
(set! (-> this free-point) (-> this used-point))
(set! (-> this used-point) (-> sampler cur-pt))
(cond
((= (-> sampler cur-pt) (-> this end-point)) (set! (-> this partial-point) 0.0) (set! (-> this summed-len) 0.0))
((= (-> sampler cur-pt) (-> this end-point))
(set! (-> this partial-point) 0.0)
(set! (-> this summed-len) 0.0))
((= (-> sampler cur-pt) (-> this next-to-last-point))
(set! (-> this summed-len) (-> this point (-> this next-to-last-point) tp-length))))))
0
@@ -379,9 +409,9 @@
(set! (-> sampler partial-pt) (-> this partial-point))
(sample-point! this (-> this sample-len) (-> sample-pos position) sampler))
(if (or (= (-> sampler cur-pt) (-> this end-point))
(= (-> sampler cur-pt) (-> this next-to-last-point))
(= (-> this point (-> sampler cur-pt) next) (-> this next-to-last-point)))
(set! (-> sampler cur-pt) (-> this used-point)))
(= (-> sampler cur-pt) (-> this next-to-last-point))
(= (-> this point (-> sampler cur-pt) next) (-> this next-to-last-point)))
(set! (-> sampler cur-pt) (-> this used-point)))
(let ((cur-pt (-> this point (-> sampler cur-pt) next)))
(when (!= cur-pt -134250495)
(let ((next-pt (-> this point cur-pt next))
@@ -396,7 +426,8 @@
(set! best-pt cur-pt)))
(set! cur-pt next-pt)
(set! next-pt (-> this point cur-pt next)))
(if (< -2.0 best-dot) (delete-point! this best-pt))))))
(if (< -2.0 best-dot)
(delete-point! this best-pt))))))
0
(none))
@@ -419,17 +450,17 @@
(= (-> this point next-pt next) (-> this end-point))
(= (-> this point next-pt next) (-> this next-to-last-point))))
(if (< (* (-> this point cur-pt tp-length)
(+ 1.0
(vector-dot (the-as vector (+ (the-as uint (-> this point 0 direction)) (* 48 cur-pt)))
(the-as vector (+ (the-as uint (the-as vector (-> this point 0 direction))) (* 48 next-pt))))))
budget)
(delete-point! this cur-pt)
(set! cur-pt next-pt))
(+ 1.0
(vector-dot (the-as vector (+ (the-as uint (-> this point 0 direction)) (* 48 cur-pt)))
(the-as vector (+ (the-as uint (the-as vector (-> this point 0 direction))) (* 48 next-pt))))))
budget)
(delete-point! this cur-pt)
(set! cur-pt next-pt))
(set! next-pt (-> this point cur-pt next)))))))
0
(none))
(defmethod add-point! ((this tracking-spline) (new-pos vector) (min-dist float) (prune-budget float) (can-prune symbol))
(defmethod add-point! ((this tracking-spline) (new-pos vector) (min-dist meters) (prune-budget meters) (can-prune symbol))
"Append new-pos when it is at least min-dist from the tail,
optionally pruning the trail to obtain a free slot."
(let ((free-pt (-> this free-point))
@@ -444,7 +475,8 @@
(prune-most-collinear! this)
(set! free-pt (-> this free-point)))
(cond
((= free-pt -134250495) (format 0 "ERROR <GMJ>: pos spline overflow~%"))
((= free-pt -134250495)
(format 0 "ERROR <GMJ>: pos spline overflow~%"))
(else
(+! (-> this summed-len) (-> this point tail-pt tp-length))
(set! (-> this free-point) (-> this point free-pt next))
@@ -454,7 +486,8 @@
(set! (-> this point free-pt next) -134250495)
(vector-copy! (-> this point free-pt position) new-pos)
(+! (-> this used-count) 1)
(if (< 0.0 prune-budget) (prune-shallow-points! this prune-budget)))))
(if (< 0.0 prune-budget)
(prune-shallow-points! this prune-budget)))))
0)
(defmethod accumulate-sample! ((this tracking-spline) (arc-len float) (out-pos vector) (sampler tracking-spline-sampler))
@@ -496,9 +529,9 @@
out-pos)
(defmethod apply-trail-correction! ((this tracking-spline) (move vector) (stop-pt int))
"Bias move along the changes in trail direction before
stop-pt. The correction is strongest on short, curved trails and fades as the recorded path
becomes straighter."
"Bias move along the changes in trail direction
before stop-pt. The correction is strongest on short, curved trails and
fades as the recorded path becomes straighter."
(let ((trail-dir (new 'stack-no-clear 'vector)))
(vector-! trail-dir (-> this point (-> this used-point) position) (-> this point (-> this end-point) position))
(let* ((chord-len (vector-length trail-dir))
@@ -510,7 +543,9 @@
((< (-> *CAMERA-bank* min-detectable-velocity) (-> this summed-len))
(vector-float*! trail-dir trail-dir (/ 1.0 chord-len))
(/ chord-len (-> this summed-len)))
(else (vector-reset! trail-dir) 0.0)))
(else
(vector-reset! trail-dir)
0.0)))
(straightness-bias (+ -0.2 chord-to-arc))
(straightness-scale (* 2.0 straightness-bias))
(alignment-weight (fmin 1.0 (fmax 0.05 straightness-scale)))
@@ -527,16 +562,17 @@
(let ((forward-dot (vector-dot seg-dir trail-dir)))
(cond
((>= 0.0 forward-dot))
(else (set! correction (* correction (fmax 0.0 (- 0.75 (fabs (* alignment-weight forward-dot)))))))))
(else
(set! correction (* correction (fmax 0.0 (- 0.75 (fabs (* alignment-weight forward-dot)))))))))
(cond
((< correction 0.0)
(if (and *debug-segment* *display-camera-marks*)
(camera-line-rel-len (-> this point next-pt position)
seg-dir
(* -40.96 correction)
(-> (new 'static 'inline-array qword 1 (new 'static 'qword :data (new 'static 'array uint32 4 #xff #xff #x0 #x80)))
0
vector4w)))
(camera-line-rel-len (-> this point next-pt position)
seg-dir
(* -40.96 correction)
(-> (new 'static 'inline-array qword 1 (new 'static 'qword :data (new 'static 'array uint32 4 #xff #xff #x0 #x80)))
0
vector4w)))
(vector--float*! move move seg-dir correction))
((and *debug-segment* *display-camera-marks*)
(camera-line-rel-len (-> this point next-pt position)
@@ -549,10 +585,11 @@
0
(none))
(defmethod follow-update! ((this tracking-spline) (pos vector) (accel float) (max-speed float))
(defmethod follow-update! ((this tracking-spline) (pos vector) (accel meters) (max-speed meters))
"Advance the trail follower toward pos using accel and
max-speed. Average 64 evenly spaced samples over the adaptive sample window, apply the
trail-direction correction, and return the smoothed position."
max-speed. Average 64 evenly spaced samples over the adaptive sample
window, apply the trail-direction correction, and return the smoothed
position."
(let ((cur-pt (-> this used-point))
(partial (-> this partial-point)))
(let ((trail-len (-> this summed-len)))
@@ -587,7 +624,7 @@
(vector-copy! (-> this old-position) pos)
pos)
(defmethod trim-to-length! ((this tracking-spline) (max-len float))
(defmethod trim-to-length! ((this tracking-spline) (max-len meters))
"Drop the oldest trail segments until its live length is
no greater than max-len."
(when (< max-len (-> this summed-len))
@@ -611,7 +648,8 @@
(+! live-count 1)
(set! cur-pt (-> this point cur-pt next)))
(when (!= live-count (-> this used-count))
(if *debug-segment* (format 0 "ERROR<GMJ>: tracking spline used count ~D actual ~D~%" (-> this used-count) live-count))
(if *debug-segment*
(format 0 "ERROR<GMJ>: tracking spline used count ~D actual ~D~%" (-> this used-count) live-count))
(set! (-> this used-count) live-count))
(let ((free-pt (-> this free-point))
(free-count 0))
@@ -620,7 +658,7 @@
(set! free-pt (-> this point free-pt next)))
(when (!= free-count (- 32 (-> this used-count)))
(if *debug-segment*
(format 0 "ERROR<GMJ>: tracking spline free count ~D actual ~D~%" (- 32 (-> this used-count)) free-count))
(format 0 "ERROR<GMJ>: tracking spline free count ~D actual ~D~%" (- 32 (-> this used-count)) free-count))
(set! (-> this free-point) -134250495)
(dotimes (i 32)
(when (not (logtest? live-mask 1))
@@ -639,14 +677,14 @@
(set! (-> self options) (-> *camera* slave-options))
(set! (-> self change-event-from) (the-as (pointer process-drawable) (-> *camera* changer))))
(else
(set! (-> self options) (the-as uint 0))
(set! (-> self options) (cam-slave-options))
(set! (-> self change-event-from) (the-as (pointer process-drawable) #f))))
(cond
(*camera-combiner*
(vector-copy! (-> self trans) (-> *camera-combiner* trans))
(matrix-copy! (-> self tracking inv-mat) (-> *camera-combiner* inv-camera-rot))
(when *camera-init-mat*
(matrix-copy! (-> self tracking inv-mat) *camera-init-mat*))
(if *camera-init-mat*
(matrix-copy! (-> self tracking inv-mat) *camera-init-mat*))
(set! (-> self fov) (-> *camera-combiner* fov))
(vector-copy! (-> self velocity) (-> *camera-combiner* velocity)))
(else
@@ -676,7 +714,9 @@
"Reinitialize the camera slave and immediately enter next-state."
(with-pp
(cam-slave-init-vars)
(let ((enter-fn (the-as (function object) enter-state))) (set! (-> pp next-state) next-state) (enter-fn))
(let ((enter-fn (the-as (function object) enter-state)))
(set! (-> pp next-state) next-state)
(enter-fn))
0
(none)))
@@ -686,13 +726,15 @@
initial-state current."
(stack-size-set! (-> self main-thread) 512)
(change-to-last-brother self)
(if (and (nonzero? camera-slave-debug) *debug-segment*) (add-connection *debug-engine* self camera-slave-debug self #f #f))
(if (and (nonzero? camera-slave-debug) *debug-segment*)
(add-connection *debug-engine* self camera-slave-debug self #f #f))
(cam-slave-init-vars)
(let ((voicebox-state 'cam-voicebox)
(call-arg (the-as basic (-> initial-state name))))
(cond
((= (the-as symbol call-arg) voicebox-state))
(camera-entity (set! (-> self cam-entity) camera-entity))
(camera-entity
(set! (-> self cam-entity) (the-as entity-camera camera-entity)))
(else
(let ((activation-event (new 'stack-no-clear 'event-message-block)))
(set! (-> activation-event from) self)
@@ -703,7 +745,8 @@
(set! call-arg *camera*)
(send-event-fn (the-as camera-master call-arg) activation-event)))))
(let ((state-enter-fn (the-as (function object object) (-> initial-state enter))))
(if state-enter-fn (state-enter-fn (the-as symbol call-arg))))
(if state-enter-fn
(state-enter-fn (the-as symbol call-arg))))
(set! (-> self enter-has-run) #t)
(set! (-> self event-hook) (-> initial-state event))
(let ((enter-state-fn (the-as (function object object) enter-state)))
@@ -725,7 +768,8 @@
(let ((next-state (the-as object (-> message param 0))))
(cam-slave-init-vars)
(let ((state-enter-fn (the-as (function object) (-> (the-as state next-state) enter))))
(if state-enter-fn (state-enter-fn)))
(if state-enter-fn
(state-enter-fn)))
(set! (-> self enter-has-run) #t)
(set! (-> self event-hook) (-> (the-as state next-state) event))
(when (= event-type 'change-state)
@@ -736,12 +780,14 @@
(cond
((-> message param 0)
(set! (-> self tracking use-point-of-interest) #t)
(vector-copy! (-> self tracking point-of-interest) (the-as vector (-> message param 0)))
(set! (-> self tracking point-of-interest quad) (-> (the-as vector (-> message param 0)) quad))
(set! (-> self tracking point-of-interest-blend target) 1.0))
(else (set! (-> self tracking use-point-of-interest) #f) (set! (-> self tracking point-of-interest-blend target) 0.0))))
(else
(set! (-> self tracking use-point-of-interest) #f)
(set! (-> self tracking point-of-interest-blend target) 0.0))))
(('teleport)
(cam-calc-follow! (-> self tracking) (-> self trans) #f)
(slave-set-rotation! (-> self tracking) (-> self trans) (the-as float (-> self options)) (-> self fov) #f))))
(slave-set-rotation! (-> self tracking) (-> self trans) (-> self options) (-> self fov) #f))))
(defbehavior cam-curve-pos camera-slave ((pos vector) (tangent vector) (path curve) (use-follow-point? symbol))
"Add the active intro and camera-path offsets to pos. When tangent is
@@ -750,10 +796,12 @@
(let ((curve-offset (new-stack-vector0)))
0.0
(let ((tangent-sample (new-stack-vector0)))
(if tangent (set! (-> tangent w) 0.0))
(if tangent
(set! (-> tangent w) 0.0))
(when (< (-> self intro-t) 1.0)
(+! (-> self intro-t) (* (-> self intro-t-step) (-> *display* time-adjust-ratio)))
(if (< 1.0 (-> self intro-t)) (set! (-> self intro-t) 1.0))
(if (< 1.0 (-> self intro-t))
(set! (-> self intro-t) 1.0))
(curve-get-pos! curve-offset (parameter-ease-sin-clamp (-> self intro-t)) (-> self intro-curve))
(vector+! curve-offset curve-offset (-> self intro-offset))
(vector+! pos pos curve-offset)
@@ -773,8 +821,8 @@
((not (-> self spline-exists)))
((= (-> self spline-follow-dist) 0.0)
(let ((spline-t (if use-follow-point?
(point->parameter (-> self index) (-> self tracking follow-pt))
(point->parameter (-> self index) (-> *camera* tpos-curr-adj)))))
(point->parameter (-> self index) (-> self tracking follow-pt))
(point->parameter (-> self index) (-> *camera* tpos-curr-adj)))))
(curve-get-pos! curve-offset spline-t (-> self spline-curve)))
(vector+! curve-offset curve-offset (-> self spline-offset))
(vector+! pos pos curve-offset))
@@ -782,8 +830,8 @@
(let ((reference-pos (new 'stack-no-clear 'vector)))
(curve-length (-> self spline-curve))
(if use-follow-point?
(vector-copy! reference-pos (-> self tracking follow-pt))
(vector-copy! reference-pos (-> *camera* tpos-curr-adj)))
(vector-copy! reference-pos (-> self tracking follow-pt))
(vector-copy! reference-pos (-> *camera* tpos-curr-adj)))
(set! (-> self spline-tt)
(curve-closest-point (-> self spline-curve) reference-pos (-> self spline-tt) 1024.0 10 (-> self spline-follow-dist))))
(curve-get-pos! curve-offset (-> self spline-tt) (-> self spline-curve))
@@ -806,9 +854,13 @@
(set! (-> self intro-t) 0.0)
(set! (-> self intro-t-step) (cam-slave-get-intro-step (-> self cam-entity)))
(set! (-> self outro-exit-value) (cam-slave-get-float (-> self cam-entity) 'intro-exitValue 0.0))
(if (= (-> self outro-exit-value) 0.0) (set! (-> self outro-exit-value) 0.5)))
(else (set! (-> self intro-t) 1.0) (set! (-> self intro-t-step) 0.0)))
(if (nonzero? (-> *camera* no-intro)) (set! (-> self intro-t) 1.0))
(if (= (-> self outro-exit-value) 0.0)
(set! (-> self outro-exit-value) 0.5)))
(else
(set! (-> self intro-t) 1.0)
(set! (-> self intro-t-step) 0.0)))
(if (nonzero? (-> *camera* no-intro))
(set! (-> self intro-t) 1.0))
0
(none))
@@ -851,10 +903,11 @@
(view-facing-angle (acos (vector-dot target-from-camera-flat target-facing-flat)))
(clamped-angle (fmax 1820.4445 view-facing-angle)))
(if (< clamped-angle 8192.0)
(vector-float*! desired-offset
desired-offset
(+ lead-scale
(* (/ (- 1.0 lead-scale) (- 1.0 (cos 32768.0))) (+ (- (cos 32768.0)) (cos (* 5.142857 (- 8192.0 clamped-angle)))))))))
(vector-float*! desired-offset
desired-offset
(+ lead-scale
(* (/ (- 1.0 lead-scale) (- 1.0 (cos (degrees 180))))
(+ (- (cos (degrees 180))) (cos (* 5.142857 (- 8192.0 clamped-angle)))))))))
(cond
((< (-> *camera* ease-t) 1.0))
((< (-> tracker follow-blend) 1.0)
@@ -863,7 +916,8 @@
(vector-float*! desired-offset desired-offset blend-factor))
(+! (-> tracker follow-blend) (/ (-> *display* time-adjust-ratio) 60))
(vector+! (-> tracker follow-off) (-> tracker follow-off) desired-offset))
(else (vector-copy! (-> tracker follow-off) desired-offset))))
(else
(vector-copy! (-> tracker follow-off) desired-offset))))
(vector+! (-> tracker follow-pt) (-> *camera* tpos-curr-adj) (-> tracker follow-off))
(vector--float*! (-> tracker follow-pt)
(-> tracker follow-pt)
@@ -874,7 +928,8 @@
(let ((normal-offset (new-stack-vector0)))
(set! (-> tracker follow-blend) 0.0)
(cond
((-> tracker no-follow) (vector-reset! normal-offset))
((-> tracker no-follow)
(vector-reset! normal-offset))
(else
(vector-! normal-offset (-> *camera* tpos-curr-adj) camera-pos)
(vector-normalize! normal-offset 1.0)
@@ -892,8 +947,8 @@
(distance-weight (fmax 0.0 distance-upper)))
(vector-float*! normal-offset (-> *camera* tgt-rot-mat vector 2) (* (lerp 2048.0 8192.0 distance-weight) behind-weight))))))
(if smooth?
(vector-seek-3d-smooth! (-> tracker follow-off) normal-offset (* 20480.0 (seconds-per-frame)) 0.05)
(set! (-> tracker follow-off quad) (-> normal-offset quad))))
(vector-seek-3d-smooth! (-> tracker follow-off) normal-offset (* 20480.0 (seconds-per-frame)) 0.05)
(vector-copy! (-> tracker follow-off) normal-offset)))
(vector+! (-> tracker follow-pt) (-> *camera* tpos-curr-adj) (-> tracker follow-off))
(vector--float*! (-> tracker follow-pt) (-> tracker follow-pt) (-> *camera* local-down) (-> *camera* target-height))))
(-> tracker follow-pt))
@@ -912,7 +967,8 @@
(when (< up-dot 0.99999)
(vector-cross! desired-up (-> camera-matrix vector 1) desired-up)
(let ((signed-sine (vector-length desired-up)))
(if (< 0.0 (vector-dot desired-up (-> camera-matrix vector 2))) (set! signed-sine (- signed-sine)))
(if (< 0.0 (vector-dot desired-up (-> camera-matrix vector 2)))
(set! signed-sine (- signed-sine)))
(matrix-axis-sin-cos! roll-correction (-> camera-matrix vector 2) signed-sine up-dot))
(matrix*! camera-matrix camera-matrix roll-correction)))))
camera-matrix)
@@ -927,33 +983,43 @@
adjusted quaternion step. The step grows with aim-vector distance; options-bits bit 2 selects
full three-dimensional rather than local-down-flattened distance."
(let ((distance-work (new-stack-vector0))
(current-rotation (new-stack-quaternion0)))
(let ((target-rotation (new-stack-quaternion0))
(delta-rotation (new-stack-quaternion0)))
0.0
(let* ((aim-distance (cond
((logtest? (the-as int options-bits) 4) (vector-length aim-vector))
(else (vector-flatten! distance-work aim-vector (-> *camera* local-down)) (vector-length distance-work))))
(distance-weight (* 0.00048828125 (+ -1024.0 aim-distance))))
(cond
((< distance-weight 0.0) (set! distance-weight 0.0))
((< 1.0 distance-weight) (set! distance-weight 1.0)))
(let ((turn-step (* 364.0889 (-> *display* time-adjust-ratio) distance-weight)))
(matrix->quaternion current-rotation current-matrix)
(matrix->quaternion target-rotation target-matrix)
(quaternion-conjugate! delta-rotation current-rotation)
(quaternion*! delta-rotation delta-rotation target-rotation)
(quaternion-normalize! delta-rotation)
(if (< (-> delta-rotation w) 0.0) (quaternion-negate! delta-rotation delta-rotation))
(let ((turn-angle (acos (-> delta-rotation w))))
(if (< (* (/ (-> *display* time-adjust-ratio) 4) turn-angle) turn-step)
(set! turn-step (* (/ (-> *display* time-adjust-ratio) 4) turn-angle)))
(cond
((< (-> delta-rotation w) 0.9999999)
(quaternion-float*! delta-rotation delta-rotation (/ (sin turn-step) (sin turn-angle)))
(set! (-> delta-rotation w) (cos turn-step)))
(else (quaternion-identity! delta-rotation))))))
(quaternion*! current-rotation current-rotation delta-rotation))
(current-rotation (new 'stack-no-clear 'quaternion)))
(vector-zero! (-> current-rotation vec))
(let ((target-rotation (new 'stack-no-clear 'quaternion)))
(vector-zero! (-> target-rotation vec))
(let ((delta-rotation (new 'stack-no-clear 'quaternion)))
(vector-zero! (-> delta-rotation vec))
0.0
(let* ((aim-distance (cond
((logtest? (the-as int options-bits) 4)
(vector-length aim-vector))
(else
(vector-flatten! distance-work aim-vector (-> *camera* local-down))
(vector-length distance-work))))
(distance-weight (* 0.00048828125 (+ -1024.0 aim-distance))))
(cond
((< distance-weight 0.0)
(set! distance-weight 0.0))
((< 1.0 distance-weight)
(set! distance-weight 1.0)))
(let ((turn-step (* 364.0889 (-> *display* time-adjust-ratio) distance-weight)))
(matrix->quaternion current-rotation current-matrix)
(matrix->quaternion target-rotation target-matrix)
(quaternion-conjugate! delta-rotation current-rotation)
(quaternion*! delta-rotation delta-rotation target-rotation)
(quaternion-normalize! delta-rotation)
(if (< (-> delta-rotation w) 0.0)
(quaternion-negate! delta-rotation delta-rotation))
(let ((turn-angle (acos (-> delta-rotation w))))
(if (< (* (/ (-> *display* time-adjust-ratio) 4) turn-angle) turn-step)
(set! turn-step (* (/ (-> *display* time-adjust-ratio) 4) turn-angle)))
(cond
((< (-> delta-rotation w) 0.9999999)
(quaternion-float*! delta-rotation delta-rotation (/ (sin turn-step) (sin turn-angle)))
(set! (-> delta-rotation w) (cos turn-step)))
(else
(quaternion-identity! delta-rotation))))))
(quaternion*! current-rotation current-rotation delta-rotation)))
(quaternion-normalize! current-rotation)
(quaternion->matrix current-matrix current-rotation)))
@@ -986,7 +1052,8 @@
(let ((right-axis-base (-> camera-matrix vector))
(horizontal-scale (* 0.8 (tan (/ fov 2)))))
(.lvf vf1 (&-> right-axis-base 0 quad))
(let ((horizontal-scale-bits horizontal-scale)) (.mov vf2 horizontal-scale-bits)))
(let ((horizontal-scale-bits horizontal-scale))
(.mov vf2 horizontal-scale-bits)))
(.add.x.vf.w vf1 vf0 vf0)
(.mul.x.vf.xyz vf1 vf1 vf2)
(.svf (&-> horizontal-edge quad) vf1))
@@ -995,7 +1062,7 @@
(let ((horizontal-edge-dot (vector-dot frustum-edge (-> camera-matrix vector 0))))
(when (< horizontal-edge-dot (fabs horizontal-target-dot))
(if (< horizontal-target-dot 0.0)
(vector--float*! frustum-edge frustum-edge (-> camera-matrix vector 0) (* 2.0 horizontal-edge-dot)))
(vector--float*! frustum-edge frustum-edge (-> camera-matrix vector 0) (* 2.0 horizontal-edge-dot)))
(matrix-from-two-vectors! correction-matrix frustum-edge target-dir)
(vector-matrix*! (-> camera-matrix vector 2) (-> camera-matrix vector 2) correction-matrix)
(vector-cross! (-> camera-matrix vector 0) (-> camera-matrix vector 1) (-> camera-matrix vector 2)))))
@@ -1009,7 +1076,8 @@
(let ((up-axis (-> camera-matrix vector 1))
(vertical-scale (* 0.525 (tan (/ fov 2)))))
(.lvf vf1 (&-> up-axis quad))
(let ((vertical-scale-bits vertical-scale)) (.mov vf2 vertical-scale-bits)))
(let ((vertical-scale-bits vertical-scale))
(.mov vf2 vertical-scale-bits)))
(.add.x.vf.w vf1 vf0 vf0)
(.mul.x.vf.xyz vf1 vf1 vf2)
(.svf (&-> vertical-edge quad) vf1))
@@ -1035,23 +1103,21 @@
(set! rotate-up? #f))
((< vertical-dot-limit 0.0)
(let ((opposite-head-dot (- (vector-dot frustum-edge target-dir))))
(if (< opposite-head-dot vertical-dot-limit) (set! vertical-dot-limit opposite-head-dot)))))))
(if (< opposite-head-dot vertical-dot-limit)
(set! vertical-dot-limit opposite-head-dot)))))))
(let ((correction-angle (if rotate-up? (- (acos vertical-dot-limit)) (acos vertical-dot-limit))))
(matrix-axis-angle! correction-matrix (-> camera-matrix vector 0) correction-angle))))
(vector-matrix*! (-> camera-matrix vector 2) (-> camera-matrix vector 2) correction-matrix))
(vector-cross! (-> camera-matrix vector 1) (-> camera-matrix vector 2) (-> camera-matrix vector 0))))
(defun slave-set-rotation! ((tracker cam-rotation-tracker) (camera-pos vector) (options-bits float) (fov float) (smooth? symbol))
;; ERROR: Unsupported inline assembly instruction kind - [mula.s f0, f3]
;; ERROR: Unsupported inline assembly instruction kind - [madda.s f1, f4]
;; ERROR: Unsupported inline assembly instruction kind - [madd.s f0, f2, f5]
(defun slave-set-rotation! ((tracker cam-rotation-tracker) (camera-pos vector) (options-bits cam-slave-options) (fov float) (smooth? symbol))
"Build tracker's inverse camera rotation from its follow point,
optional point of interest and tilt; keep the target in frame, optionally blend toward the new
orientation, and remove roll. options-bits is a raw cam-slave-options word carried in a float."
;; Start from the follow point and blend toward a point of interest without
;; changing the aim-vector length. The tilt guard leaves 15 degrees of room
;; before either vertical pole so the pitch adjustment cannot flip the view.
;; Underwater framing narrows the effective field of view as far as one
;; quarter, then the safe-frame correction, optional orientation blend, and
;; final roll removal produce the inverse camera rotation.
(local-vars (forward-down-dot float) (tilt-matrix matrix))
orientation, and remove roll."
(local-vars (output-matrix matrix) (forward-down-dot float))
(rlet ((vf0 :class vf)
(vf4 :class vf)
(vf5 :class vf)
@@ -1069,46 +1135,52 @@
(vector-! point-of-interest-vector (-> tracker point-of-interest) camera-pos)
(vector-normalize! point-of-interest-vector (* aim-distance (-> tracker point-of-interest-blend value)))
(let ((blended-aim-out aim-vector))
(let ((base-aim aim-vector)) (.mov.vf.w vf6 vf0) (.lvf vf4 (&-> base-aim quad)))
(let ((base-aim aim-vector))
(.mov.vf.w vf6 vf0)
(.lvf vf4 (&-> base-aim quad)))
(.lvf vf5 (&-> point-of-interest-vector quad))
(.add.vf.xyz vf6 vf4 vf5)
(.svf (&-> blended-aim-out quad) vf6))
(vector-normalize! aim-vector aim-distance))))
(else (vector-! aim-vector (-> tracker follow-pt) camera-pos)))
(else
(vector-! aim-vector (-> tracker follow-pt) camera-pos)))
(forward-down->inv-matrix target-matrix aim-vector (-> *camera* local-down))
(when (!= tilt-angle 0.0)
0.0
0.0
(set! tilt-matrix (new 'stack-no-clear 'matrix))
(let ((aim-direction (new 'stack-no-clear 'vector)))
(vector-normalize-copy! aim-direction aim-vector 1.0)
(let* ((down-axis (-> *camera* local-down))) (set! forward-down-dot (vector-dot aim-direction down-axis))))
(let* ((down-dot forward-down-dot)
(vertical-angle (acos (fabs down-dot))))
(cond
((< 0.0 tilt-angle)
(set! tilt-angle
(if (< 0.0 down-dot)
(fmin tilt-angle (fmax 0.0 (+ -2730.6667 vertical-angle)))
(fmin tilt-angle (fmax 0.0 (- 32768.0 (+ 2730.6667 vertical-angle)))))))
((< tilt-angle 0.0)
(set! tilt-angle
(if (< 0.0 down-dot)
(fmax tilt-angle (- (fmax 0.0 (- 32768.0 (+ 2730.6667 vertical-angle)))))
(fmax tilt-angle (- (fmax 0.0 (+ -2730.6667 vertical-angle)))))))))
(matrix-rotate-x! tilt-matrix tilt-angle)
(matrix*! target-matrix tilt-matrix target-matrix)))
(let ((tilt-matrix (new 'stack-no-clear 'matrix)))
(let ((aim-direction (new 'stack-no-clear 'vector)))
(vector-normalize-copy! aim-direction aim-vector 1.0)
(let* ((down-axis (-> *camera* local-down)))
(set! forward-down-dot (vector-dot aim-direction down-axis))))
(let* ((down-dot forward-down-dot)
(vertical-angle (acos (fabs down-dot))))
(cond
((< 0.0 tilt-angle)
(set! tilt-angle
(if (< 0.0 down-dot)
(fmin tilt-angle (fmax 0.0 (+ -2730.6667 vertical-angle)))
(fmin tilt-angle (fmax 0.0 (- 32768.0 (+ 2730.6667 vertical-angle)))))))
((< tilt-angle 0.0)
(set! tilt-angle
(if (< 0.0 down-dot)
(fmax tilt-angle (- (fmax 0.0 (- 32768.0 (+ 2730.6667 vertical-angle)))))
(fmax tilt-angle (- (fmax 0.0 (+ -2730.6667 vertical-angle)))))))))
(matrix-rotate-x! tilt-matrix tilt-angle)
(matrix*! target-matrix tilt-matrix target-matrix))))
(if (and (= (-> *camera* under-water) 2) *target* (!= (-> *target* next-state name) 'target-swim-up))
(set! (-> tracker underwater-blend target) 1.0)
(set! (-> tracker underwater-blend target) 0.0))
(set! (-> tracker underwater-blend target) 1.0)
(set! (-> tracker underwater-blend target) 0.0))
(vector-into-frustum-nosmooth! target-matrix camera-pos (lerp-clamp fov (/ fov 4) (-> tracker underwater-blend value)))
(cond
(smooth? (slave-matrix-blend-2 (-> tracker inv-mat) options-bits aim-vector target-matrix))
(else
(matrix-copy! (-> tracker inv-mat) target-matrix))))
(set! output-matrix
(cond
(smooth?
(slave-matrix-blend-2 (-> tracker inv-mat) (the-as float options-bits) aim-vector target-matrix)
output-matrix)
(else
(matrix-copy! (-> tracker inv-mat) target-matrix)))))
(mat-remove-z-rot (-> tracker inv-mat) (-> *camera* local-down))
0
(none)))
0))
(defun v-slrp2! ((out vector) (from-vector vector) (to-vector vector) (t float) (plane-normal vector) (max-angle float))
"Spherically interpolate from-vector toward to-vector by t while
@@ -1119,56 +1191,51 @@
;; angular arc without the length collapse of a linear vector blend. With a
;; plane normal, only the in-plane direction rotates; the component on the
;; normal is restored and interpolated independently.
(local-vars
(direction-dot float)
(to-length float)
(from-length float)
(angle-limit float)
(to-direction vector)
(rotation-matrix matrix))
(set! angle-limit max-angle)
(let ((from-direction (new-stack-vector0)))
(set! to-direction (new 'stack-no-clear 'vector))
(set! (-> to-direction quad) (the-as uint128 0))
(local-vars (direction-dot float) (to-length float) (from-length float))
(let ((angle-limit max-angle)
(from-direction (new-stack-vector0))
(to-direction (new-stack-vector0)))
1.0
1.0
(let ((rotation-axis (new-stack-vector0)))
0.0
1.0
(set! rotation-matrix (new 'stack-no-clear 'matrix))
(set! (-> rotation-matrix vector 0 quad) (the-as uint128 0))
(set! (-> rotation-matrix vector 1 quad) (the-as uint128 0))
(set! (-> rotation-matrix vector 2 quad) (the-as uint128 0))
(set! (-> rotation-matrix vector 3 quad) (the-as uint128 0))
(cond
((< 1.0 t) (set! t 1.0))
((< t 0.0) (set! t 0.0)))
(cond
(plane-normal
(vector-flatten! from-direction from-vector plane-normal)
(vector-flatten! to-direction to-vector plane-normal)
(set! from-length (vector-normalize-ret-len! from-direction 1.0))
(set! to-length (vector-normalize-ret-len! to-direction 1.0))
(vector-normalize! (vector-cross! rotation-axis to-direction from-direction) 1.0)
(let ((axis-side (vector-dot plane-normal rotation-axis)))
(vector-normalize-copy! rotation-axis plane-normal 1.0)
(if (< axis-side 0.0) (vector-negate! rotation-axis rotation-axis))))
(else
(set! (-> from-direction quad) (-> from-vector quad))
(vector-copy! to-direction to-vector)
(set! from-length (vector-normalize-ret-len! from-direction 1.0))
(set! to-length (vector-normalize-ret-len! to-direction 1.0))
(vector-normalize! (vector-cross! rotation-axis to-vector from-vector) 1.0)))
(let ((acos-fn acos))
(let* ((from-direction-copy from-direction)) (set! direction-dot (vector-dot from-direction-copy to-direction)))
(let* ((angle (acos-fn direction-dot))
(step-angle (* t angle)))
(when (< angle-limit step-angle)
(set! step-angle angle-limit)
(set! t (/ angle-limit angle)))
(let ((cos-angle (cos step-angle)))
(matrix-axis-sin-cos! rotation-matrix rotation-axis (sqrtf (- 1.0 (square cos-angle))) cos-angle))))
(vector-matrix*! out from-direction rotation-matrix)
(let ((rotation-matrix (new 'stack-no-clear 'matrix)))
(set! (-> rotation-matrix vector 0 quad) (the-as uint128 0))
(set! (-> rotation-matrix vector 1 quad) (the-as uint128 0))
(set! (-> rotation-matrix vector 2 quad) (the-as uint128 0))
(set! (-> rotation-matrix vector 3 quad) (the-as uint128 0))
(cond
((< 1.0 t) (set! t 1.0))
((< t 0.0) (set! t 0.0)))
(cond
(plane-normal
(vector-flatten! from-direction from-vector plane-normal)
(vector-flatten! to-direction to-vector plane-normal)
(set! from-length (vector-normalize-ret-len! from-direction 1.0))
(set! to-length (vector-normalize-ret-len! to-direction 1.0))
(vector-normalize! (vector-cross! rotation-axis to-direction from-direction) 1.0)
(let ((axis-side (vector-dot plane-normal rotation-axis)))
(vector-normalize-copy! rotation-axis plane-normal 1.0)
(if (< axis-side 0.0)
(vector-negate! rotation-axis rotation-axis))))
(else
(vector-copy! from-direction from-vector)
(set! (-> to-direction quad) (-> to-vector quad))
(set! from-length (vector-normalize-ret-len! from-direction 1.0))
(set! to-length (vector-normalize-ret-len! to-direction 1.0))
(vector-normalize! (vector-cross! rotation-axis to-vector from-vector) 1.0)))
(let ((acos-fn acos))
(let* ((from-direction-copy from-direction))
(set! direction-dot (vector-dot from-direction-copy to-direction)))
(let* ((angle (acos-fn direction-dot))
(step-angle (* t angle)))
(when (< angle-limit step-angle)
(set! step-angle angle-limit)
(set! t (/ angle-limit angle)))
(let ((cos-angle (cos step-angle)))
(matrix-axis-sin-cos! rotation-matrix rotation-axis (sqrtf (- 1.0 (square cos-angle))) cos-angle))))
(vector-matrix*! out from-direction rotation-matrix))
(vector-normalize! out (lerp from-length to-length t))
(when plane-normal
(vector+float*! out out rotation-axis (vector-dot from-vector rotation-axis))
@@ -1182,11 +1249,10 @@
"Spherically interpolate from-vector toward to-vector by no more than
max-angle, using the required angular fraction and interpolating length separately. An optional
plane-normal constrains the rotation plane."
(local-vars (direction-dot float) (to-length float) (from-length float) (angle-limit float) (to-direction vector))
(set! angle-limit max-angle)
(let ((from-direction (new-stack-vector0)))
(set! to-direction (new 'stack-no-clear 'vector))
(set! (-> to-direction quad) (the-as uint128 0))
(local-vars (direction-dot float) (to-length float) (from-length float))
(let ((angle-limit max-angle)
(from-direction (new-stack-vector0))
(to-direction (new-stack-vector0)))
0.0
0.0
(let ((rotation-axis (new-stack-vector0))
@@ -1202,15 +1268,17 @@
(vector-normalize! (vector-cross! rotation-axis to-direction from-direction) 1.0)
(let ((axis-side (vector-dot plane-normal rotation-axis)))
(vector-normalize-copy! rotation-axis plane-normal 1.0)
(if (< axis-side 0.0) (vector-negate! rotation-axis rotation-axis))))
(if (< axis-side 0.0)
(vector-negate! rotation-axis rotation-axis))))
(else
(set! (-> from-direction quad) (-> from-vector quad))
(vector-copy! to-direction to-vector)
(vector-copy! from-direction from-vector)
(set! (-> to-direction quad) (-> to-vector quad))
(set! from-length (vector-normalize-ret-len! from-direction 1.0))
(set! to-length (vector-normalize-ret-len! to-direction 1.0))
(vector-normalize! (vector-cross! rotation-axis to-vector from-vector) 1.0)))
(let ((acos-fn acos))
(let* ((from-direction-copy from-direction)) (set! direction-dot (vector-dot from-direction-copy to-direction)))
(let* ((from-direction-copy from-direction))
(set! direction-dot (vector-dot from-direction-copy to-direction)))
(let ((angle (acos-fn direction-dot)))
(when (< angle-limit angle)
(set! fraction (/ angle-limit angle))