World/Brain: lit pathways + experience-scaled neurons
- brain edges now use per-vertex colors driven by endpoint activity, so a firing neuron lights its pathways (gradient from the brighter end) while dormant connections stay faint — the wiring visibly comes alive. - neuron size now grows with cumulative activity (experience), so the agents that do the most work read as the largest, most-developed neurons. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
9725d620cf
commit
05cf132957
@@ -259,12 +259,14 @@ export function WorldCanvas({ roots, selectedId, onSelect, expanded, onToggleExp
|
|||||||
const brainEdgeGeom = new THREE.BufferGeometry();
|
const brainEdgeGeom = new THREE.BufferGeometry();
|
||||||
const brainEdges = new THREE.LineSegments(
|
const brainEdges = new THREE.LineSegments(
|
||||||
brainEdgeGeom,
|
brainEdgeGeom,
|
||||||
new THREE.LineBasicMaterial({ color: 0x6fb6ff, transparent: true, opacity: 0.14, blending: THREE.AdditiveBlending, depthWrite: false }),
|
new THREE.LineBasicMaterial({ vertexColors: true, transparent: true, opacity: 0.95, blending: THREE.AdditiveBlending, depthWrite: false }),
|
||||||
);
|
);
|
||||||
brainGroup.add(brainEdges);
|
brainGroup.add(brainEdges);
|
||||||
const brainPositions = new Map<string, THREE.Vector3>();
|
const brainPositions = new Map<string, THREE.Vector3>();
|
||||||
const neuronAct = new Map<string, number>();
|
const neuronAct = new Map<string, number>();
|
||||||
|
const neuronExp = new Map<string, number>(); // cumulative experience → neuron size
|
||||||
const brainAdj = new Map<string, string[]>();
|
const brainAdj = new Map<string, string[]>();
|
||||||
|
let brainEdgeIds: string[] = []; // flat [a0,b0,a1,b1,…] for per-edge lighting
|
||||||
let brainCount = -1;
|
let brainCount = -1;
|
||||||
|
|
||||||
// particle system (sparks + trails): additive points, ring buffer, RGB→0 fade
|
// particle system (sparks + trails): additive points, ring buffer, RGB→0 fade
|
||||||
@@ -376,6 +378,7 @@ export function WorldCanvas({ roots, selectedId, onSelect, expanded, onToggleExp
|
|||||||
brainAdj.clear();
|
brainAdj.clear();
|
||||||
const pos = ids.map((id) => brainPositions.get(id)!);
|
const pos = ids.map((id) => brainPositions.get(id)!);
|
||||||
const segs: number[] = [];
|
const segs: number[] = [];
|
||||||
|
const pairs: string[] = [];
|
||||||
for (let i = 0; i < ids.length; i++) {
|
for (let i = 0; i < ids.length; i++) {
|
||||||
const ds = ids.map((_, j) => ({ j, d: i === j ? Infinity : pos[i].distanceToSquared(pos[j]) }));
|
const ds = ids.map((_, j) => ({ j, d: i === j ? Infinity : pos[i].distanceToSquared(pos[j]) }));
|
||||||
ds.sort((a, b) => a.d - b.d);
|
ds.sort((a, b) => a.d - b.d);
|
||||||
@@ -384,11 +387,16 @@ export function WorldCanvas({ roots, selectedId, onSelect, expanded, onToggleExp
|
|||||||
for (let n = 0; n < k; n++) {
|
for (let n = 0; n < k; n++) {
|
||||||
const j = ds[n].j;
|
const j = ds[n].j;
|
||||||
nbrs.push(ids[j]);
|
nbrs.push(ids[j]);
|
||||||
if (i < j) segs.push(pos[i].x, pos[i].y, pos[i].z, pos[j].x, pos[j].y, pos[j].z);
|
if (i < j) {
|
||||||
|
segs.push(pos[i].x, pos[i].y, pos[i].z, pos[j].x, pos[j].y, pos[j].z);
|
||||||
|
pairs.push(ids[i], ids[j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
brainAdj.set(ids[i], nbrs);
|
brainAdj.set(ids[i], nbrs);
|
||||||
}
|
}
|
||||||
|
brainEdgeIds = pairs;
|
||||||
brainEdgeGeom.setAttribute("position", new THREE.Float32BufferAttribute(segs, 3));
|
brainEdgeGeom.setAttribute("position", new THREE.Float32BufferAttribute(segs, 3));
|
||||||
|
brainEdgeGeom.setAttribute("color", new THREE.Float32BufferAttribute(new Float32Array(segs.length), 3));
|
||||||
brainEdgeGeom.attributes.position.needsUpdate = true;
|
brainEdgeGeom.attributes.position.needsUpdate = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -422,8 +430,11 @@ export function WorldCanvas({ roots, selectedId, onSelect, expanded, onToggleExp
|
|||||||
if (Math.random() < dt * 0.5) act = Math.min(1, act + 0.08); // resting shimmer → the brain breathes
|
if (Math.random() < dt * 0.5) act = Math.min(1, act + 0.08); // resting shimmer → the brain breathes
|
||||||
act = Math.max(ne.agent ? 0.06 : 0.025, act - dt * 0.22);
|
act = Math.max(ne.agent ? 0.06 : 0.025, act - dt * 0.22);
|
||||||
neuronAct.set(ne.id, act);
|
neuronAct.set(ne.id, act);
|
||||||
|
let exp = neuronExp.get(ne.id) ?? 0;
|
||||||
|
exp = Math.min(1, exp + act * dt * 0.15); // experience grows with activity
|
||||||
|
neuronExp.set(ne.id, exp);
|
||||||
g.position.copy(pos);
|
g.position.copy(pos);
|
||||||
const base = ne.agent ? 16 : 8;
|
const base = (ne.agent ? 16 : 8) + exp * (ne.agent ? 16 : 7);
|
||||||
const gs = base + act * (ne.agent ? 36 : 16);
|
const gs = base + act * (ne.agent ? 36 : 16);
|
||||||
g.scale.set(gs, gs, 1);
|
g.scale.set(gs, gs, 1);
|
||||||
const gm = g.material as THREE.SpriteMaterial;
|
const gm = g.material as THREE.SpriteMaterial;
|
||||||
@@ -445,6 +456,25 @@ export function WorldCanvas({ roots, selectedId, onSelect, expanded, onToggleExp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// light up pathways by endpoint activity (lit pathways stand out; gradient
|
||||||
|
// from each end so the brighter neuron dominates its edges)
|
||||||
|
const ecol = brainEdgeGeom.getAttribute("color") as THREE.BufferAttribute | undefined;
|
||||||
|
if (ecol) {
|
||||||
|
const arr = ecol.array as Float32Array;
|
||||||
|
for (let e = 0; e + 1 < brainEdgeIds.length; e += 2) {
|
||||||
|
const va = 0.05 + (neuronAct.get(brainEdgeIds[e]) ?? 0) * 0.95;
|
||||||
|
const vb = 0.05 + (neuronAct.get(brainEdgeIds[e + 1]) ?? 0) * 0.95;
|
||||||
|
const ia = e * 3;
|
||||||
|
const ib = (e + 1) * 3;
|
||||||
|
arr[ia] = 0.43 * va;
|
||||||
|
arr[ia + 1] = 0.71 * va;
|
||||||
|
arr[ia + 2] = va;
|
||||||
|
arr[ib] = 0.43 * vb;
|
||||||
|
arr[ib + 1] = 0.71 * vb;
|
||||||
|
arr[ib + 2] = vb;
|
||||||
|
}
|
||||||
|
ecol.needsUpdate = true;
|
||||||
|
}
|
||||||
for (const [id, g] of neuronGlows) {
|
for (const [id, g] of neuronGlows) {
|
||||||
if (!seen.has(id)) {
|
if (!seen.has(id)) {
|
||||||
brainGroup.remove(g);
|
brainGroup.remove(g);
|
||||||
|
|||||||
Reference in New Issue
Block a user