Skip to content

Commit c8d7bdd

Browse files
committed
fix(brain): click-pin raycast + burstier idle firing
- Satellites.setData now calls computeBoundingSphere on both the body and halo InstancedMesh after writing positions. Three.js raycaster's intersectObject pre-tests against the bounding sphere; without one explicitly computed the default tiny sphere at origin rejected every hit, so click-pin always returned null and "click satellites to inspect" went nowhere. - IdleSimulator now fires bursts of 1-3 fakes per scheduled tick, staggered 90ms apart, instead of a single fake. Real /brain/firing arrival immediately cancels every queued burst timer in addition to the next-tick timer. Visually: constellation feels noticeably more alive at rest without changing the cadence of real-event response. No public-API changes. Tests: 165 passed.
1 parent 2ab7e97 commit c8d7bdd

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

desktop/cortex-control-center/src/brain-v2/IdleSimulator.js

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,49 @@ import { mulberry32 } from "./util/mulberry32.js";
33
const IDLE_THRESHOLD_MS = 6_000;
44
const FAKE_INTERVAL_MIN_MS = 900;
55
const FAKE_INTERVAL_MAX_MS = 2_400;
6+
const BURST_MIN = 1;
7+
const BURST_MAX = 3;
8+
const BURST_STAGGER_MS = 90;
69

710
export function createIdleSimulator({ onFake, getNodeIds, seed = Date.now() }) {
811
let lastReal = performance.now();
912
let timer = null;
13+
const burstTimers = new Set();
1014
let disposed = false;
1115
const rand = mulberry32(seed);
1216

17+
function fireBurst() {
18+
const ids = (typeof getNodeIds === "function" ? getNodeIds() : []) || [];
19+
if (!ids.length || typeof onFake !== "function") return;
20+
const burst = BURST_MIN + Math.floor(rand() * (BURST_MAX - BURST_MIN + 1));
21+
for (let i = 0; i < burst; i += 1) {
22+
const wait = i * BURST_STAGGER_MS;
23+
const t = setTimeout(() => {
24+
burstTimers.delete(t);
25+
if (disposed) return;
26+
if (performance.now() - lastReal < IDLE_THRESHOLD_MS) return;
27+
const pick = ids[Math.floor(rand() * ids.length)];
28+
if (pick) onFake(pick);
29+
}, wait);
30+
burstTimers.add(t);
31+
}
32+
}
33+
1334
function schedule() {
1435
if (disposed) return;
1536
const wait = FAKE_INTERVAL_MIN_MS + rand() * (FAKE_INTERVAL_MAX_MS - FAKE_INTERVAL_MIN_MS);
1637
timer = setTimeout(() => {
1738
if (disposed) return;
1839
const idle = performance.now() - lastReal;
19-
if (idle >= IDLE_THRESHOLD_MS) {
20-
const ids = (typeof getNodeIds === "function" ? getNodeIds() : []) || [];
21-
if (ids.length > 0) {
22-
const pick = ids[Math.floor(rand() * ids.length)];
23-
if (pick && typeof onFake === "function") onFake(pick);
24-
}
25-
}
40+
if (idle >= IDLE_THRESHOLD_MS) fireBurst();
2641
schedule();
2742
}, wait);
2843
}
2944

3045
function noteRealEvent() {
3146
lastReal = performance.now();
47+
for (const t of burstTimers) clearTimeout(t);
48+
burstTimers.clear();
3249
if (timer) {
3350
clearTimeout(timer);
3451
timer = null;
@@ -46,9 +63,12 @@ export function createIdleSimulator({ onFake, getNodeIds, seed = Date.now() }) {
4663
clearTimeout(timer);
4764
timer = null;
4865
}
66+
for (const t of burstTimers) clearTimeout(t);
67+
burstTimers.clear();
4968
},
5069
};
5170
}
5271

5372
export const IDLE_THRESHOLD = IDLE_THRESHOLD_MS;
5473
export const FAKE_INTERVAL_RANGE = [FAKE_INTERVAL_MIN_MS, FAKE_INTERVAL_MAX_MS];
74+
export const BURST_RANGE = [BURST_MIN, BURST_MAX];

desktop/cortex-control-center/src/brain-v2/Satellites.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ export function createSatellites({ scene }) {
7575
bodies.count = slots.length;
7676
halos.count = slots.length;
7777
writeAll();
78+
bodies.computeBoundingSphere();
79+
halos.computeBoundingSphere();
7880
}
7981

8082
function writeAll(now = performance.now()) {

0 commit comments

Comments
 (0)