.
Some checks failed
Deploy to Pages / build (pull_request) Failing after 3m15s

This commit is contained in:
Andras Schmelczer 2026-05-13 22:13:15 +01:00
parent 39b0160064
commit 2347ecd201
71 changed files with 3799 additions and 1606 deletions

View file

@ -12,11 +12,15 @@ const INITIAL_AGENT_COUNT = appConfig.simulation.initialAgentCount;
const MIN_STROKE_AGENT_COUNT = appConfig.simulation.stroke.minAgentCount;
const MAX_STROKE_AGENT_COUNT = appConfig.simulation.stroke.maxAgentCount;
const STROKE_AGENT_DENSITY_MULTIPLIER = appConfig.simulation.stroke.densityMultiplier;
const ADAPTIVE_CAP_MIN = appConfig.simulation.budget.adaptiveCapMin;
const ADAPTIVE_CAP_DECREASE_AGENTS_PER_SECOND =
appConfig.simulation.budget.adaptiveCapDecreaseAgentsPerSecond;
export class AgentPopulation {
private activeCount = 0;
private targetBudget = appConfig.simulation.budget.initialTargetAgentBudget;
private replacementCursor = 0;
private canExpandAdaptiveCap = true;
private shouldCompactAfterErase = false;
private isCompacting = false;
private readonly strokeAgentData = new Float32Array(
@ -38,6 +42,7 @@ export class AgentPopulation {
}
public initializeIntroAgents(canvasSize: vec2): void {
settings.agentBudgetMax = this.clampAdaptiveCap(settings.agentBudgetMax);
this.targetBudget = Math.min(
this.pipeline.maxAgentCount,
settings.agentBudgetMax,
@ -53,6 +58,7 @@ export class AgentPopulation {
}
public onVibeChanged(): void {
settings.agentBudgetMax = this.clampAdaptiveCap(settings.agentBudgetMax);
this.targetBudget = Math.min(
this.targetBudget,
settings.agentBudgetMax,
@ -65,7 +71,9 @@ export class AgentPopulation {
smoothedFps: number,
refreshTargetFps: number
): void {
const cap = Math.min(settings.agentBudgetMax, this.pipeline.maxAgentCount);
this.updateAdaptiveCap(deltaTime, smoothedFps, refreshTargetFps);
const cap = this.clampAdaptiveCap(settings.agentBudgetMax);
if (
this.targetBudget < cap &&
smoothedFps > refreshTargetFps * appConfig.simulation.budget.fpsHeadroom
@ -147,6 +155,8 @@ export class AgentPopulation {
}
const count = data.length / AGENT_FLOAT_COUNT;
this.expandAdaptiveCapForPendingAgents(count);
const available = Math.max(0, this.targetBudget - this.activeCount);
const appendCount = Math.min(count, available);
@ -178,4 +188,60 @@ export class AgentPopulation {
this.replacementCursor = (targetAgentOffset + chunkAgentCount) % this.activeCount;
}
}
private updateAdaptiveCap(
deltaTime: number,
smoothedFps: number,
refreshTargetFps: number
): void {
const previousCap = this.clampAdaptiveCap(settings.agentBudgetMax);
this.canExpandAdaptiveCap =
smoothedFps >= refreshTargetFps * appConfig.simulation.budget.fpsHeadroom;
if (this.canExpandAdaptiveCap) {
settings.agentBudgetMax = previousCap;
return;
}
const decrease = Math.max(
1,
Math.ceil(ADAPTIVE_CAP_DECREASE_AGENTS_PER_SECOND * deltaTime)
);
const nextCap = this.clampAdaptiveCap(previousCap - decrease);
settings.agentBudgetMax = nextCap;
this.targetBudget = Math.min(this.targetBudget, nextCap);
if (this.activeCount > this.targetBudget) {
this.activeCount = Math.max(this.targetBudget, this.activeCount - decrease);
this.replacementCursor =
this.activeCount === 0 ? 0 : this.replacementCursor % this.activeCount;
}
}
private expandAdaptiveCapForPendingAgents(requestedAgentCount: number): void {
const available = Math.max(0, this.targetBudget - this.activeCount);
if (requestedAgentCount <= available || !this.canExpandAdaptiveCap) {
return;
}
const currentCap = this.clampAdaptiveCap(settings.agentBudgetMax);
if (this.targetBudget < currentCap) {
return;
}
const pendingAgentCount = requestedAgentCount - available;
const nextCap = this.clampAdaptiveCap(currentCap + pendingAgentCount);
settings.agentBudgetMax = nextCap;
this.targetBudget = Math.max(
this.targetBudget,
Math.min(nextCap, this.activeCount + requestedAgentCount)
);
}
private clampAdaptiveCap(value: number): number {
const pipelineCap = Math.max(0, Math.floor(this.pipeline.maxAgentCount));
const minCap = Math.min(ADAPTIVE_CAP_MIN, pipelineCap);
const finiteValue = Number.isFinite(value) ? value : minCap;
return Math.min(pipelineCap, Math.max(minCap, Math.round(finiteValue)));
}
}