Update GUI

This commit is contained in:
vHawk 2022-07-11 03:05:09 +03:00
parent a3c03cafef
commit c84a3b46b7
15 changed files with 60 additions and 52 deletions

View file

@ -16,10 +16,6 @@ It is important to prevent ants from following pheromone trails left by those an
Pheromone trails left by ants evaporate and diffuse over time.
## Compute pipeline overview
TODO
## References
- https://softologyblog.wordpress.com/2020/03/21/ant-colony-simulations/

View file

@ -21,10 +21,9 @@ export default new class App {
private renderer: Renderer = new Renderer(<HTMLCanvasElement>document.getElementById('canvas'));
private scenes: SceneCollection;
private gui: GUI = new GUI();
private renderLoop = (deltaTime: number): void => this.render(deltaTime);
private simInterval: NodeJS.Timer;
private simulationStepsPerSecond: number = 0;
private simStarted: boolean = false;
private renderLoop = (time: number): void => this.render(time);
private lastTime: number = 0;
private queuedSimSteps: number = 0;
constructor() {
this.initScenes();
@ -35,9 +34,6 @@ export default new class App {
this.renderLoop(0);
this.simulationStepsPerSecond = Config.simulationStepsPerSecond;
this.updateSimulationInterval();
this.gui.on('antsCount', () => {
this.resetRenderer();
});
@ -45,27 +41,12 @@ export default new class App {
this.gui.on('worldSize', () => {
this.resetRenderer();
});
this.gui.on('simulationStepsPerSecond', () => {
this.simulationStepsPerSecond = Config.simulationStepsPerSecond;
this.updateSimulationInterval();
});
}
private resetRenderer() {
this.renderer.reset(this.scenes);
}
private updateSimulationInterval() {
clearInterval(this.simInterval);
this.simInterval = setInterval(() => {
this.simulationStep();
this.simStarted = true;
}, 1000 / this.simulationStepsPerSecond);
}
private initScenes() {
this.scenes = {
ants: new AntsComputeScene(this.renderer),
@ -90,19 +71,31 @@ export default new class App {
private simulationStep() {
for (const scene of Object.values(this.scenes)) {
scene.update(0);
scene.update();
}
this.renderer.renderSimulation(this.scenes);
}
private render(deltaTime: number) {
private render(time: number) {
requestAnimationFrame(this.renderLoop);
if (!this.simStarted) {
const deltaTime = time - this.lastTime;
const simStepsToDo = deltaTime / 1000 * Config.simulationStepsPerSecond;
this.queuedSimSteps += simStepsToDo;
while (this.queuedSimSteps >= 1) {
this.simulationStep();
--this.queuedSimSteps;
}
if (time === 0) {
return;
}
this.renderer.renderToScreen(this.scenes);
this.lastTime = time;
}
}

View file

@ -1,6 +1,6 @@
export default {
worldSize: 1024,
antsCount: 64 ** 2,
antsCount: 12,
simulationStepsPerSecond: 60,
scentThreshold: 0.01,
scentFadeOutFactor: 0.998,

View file

@ -12,19 +12,28 @@ export default class GUI extends EventEmitter {
const simFolder = this.gui.addFolder('Simulation');
simFolder.add(Config, 'worldSize', 256, 4096).onChange(() => {
this.emit('worldSize');
});
simFolder.add(Config, 'antsCount', 1, 1e6).onChange(() => {
this.emit('antsCount');
});
simFolder.add(Config, 'simulationStepsPerSecond', 1, 500).onChange(() => {
this.emit('simulationStepsPerSecond');
});
simFolder.add(Config, 'worldSize', 256, 4096)
.name('World size')
.step(1)
.onChange(() => {
this.emit('worldSize');
});
simFolder.add(Config, 'antsCount', 0, 22)
.name('Ants count 2^')
.step(1)
.onChange(() => {
this.emit('antsCount');
});
simFolder.add(Config, 'simulationStepsPerSecond', 1, 500)
.name('Simulation steps per second')
.step(1)
.onChange(() => {
this.emit('simulationStepsPerSecond');
});
const controlsFolder = this.gui.addFolder('Controls');
controlsFolder.add(Config, 'brushRadius', 1, 100);
controlsFolder.add(Config, 'brushRadius', 1, 100).name('Brush radius');
simFolder.open();
controlsFolder.open();

View file

@ -23,7 +23,7 @@ export default class Renderer {
}
private initResources() {
const antTextureSize = Math.round(Math.sqrt(Config.antsCount));
const antTextureSize = Math.round(Math.sqrt(2 ** Config.antsCount));
this.resources = {
worldRenderTarget: new THREE.WebGLRenderTarget(Config.worldSize, Config.worldSize, {
@ -139,7 +139,7 @@ export default class Renderer {
}
public reset(scenes: SceneCollection) {
const antTextureSize = Math.ceil(Math.sqrt(Config.antsCount));
const antTextureSize = Math.round(Math.sqrt(2 ** Config.antsCount));
this.resources.worldRenderTarget.setSize(Config.worldSize, Config.worldSize)
this.renderer.setRenderTarget(this.resources.worldRenderTarget);

View file

@ -25,7 +25,7 @@
</style>
</head>
<body>
<div id="info">Controls:<br/>Q - draw home cells<br/>W - draw food cells<br/>E - draw obstacle<br/>Drag and scroll to move the camera</div>
<div id="info">Controls:<br/>Q - draw home cells<br/>W - draw food cells<br/>E - draw obstacle<br/>R - erase<br/>Drag and scroll to move the camera</div>
<canvas id="canvas"></canvas>
</body>
</html>

View file

@ -15,5 +15,5 @@ export default abstract class AbstractScene extends THREE.Scene {
public abstract resize(width: number, height: number): void;
public abstract update(deltaTime: number): void;
public abstract update(): void;
}

View file

@ -52,7 +52,7 @@ export default class AntsComputeScene extends AbstractScene {
}
public update(deltaTime: number) {
public update() {
this.material.uniforms.uTime.value = performance.now();
}
}

View file

@ -50,7 +50,7 @@ export default class AntsDiscretizeScene extends AbstractScene {
}
public update(deltaTime: number) {
public update() {
}
}

View file

@ -40,7 +40,7 @@ export default class DrawScene extends AbstractScene {
}
public update(deltaTime: number) {
public update() {
}
}

View file

@ -11,7 +11,8 @@ enum PointerState {
None,
Food,
Home,
Obstacle
Obstacle,
Erase
}
export default class ScreenScene extends AbstractScene {
@ -144,6 +145,10 @@ export default class ScreenScene extends AbstractScene {
this.drawMode = PointerState.Obstacle;
break;
}
case 'KeyR': {
this.drawMode = PointerState.Erase;
break;
}
}
});
@ -198,7 +203,7 @@ export default class ScreenScene extends AbstractScene {
this.renderHeight = height;
}
public update(deltaTime: number) {
public update() {
}
}

View file

@ -37,7 +37,7 @@ export default class WorldBlurScene extends AbstractScene {
}
public update(deltaTime: number) {
public update() {
}
}

View file

@ -38,7 +38,7 @@ export default class WorldComputeScene extends AbstractScene {
}
public update(deltaTime: number) {
public update() {
}
}

View file

@ -23,8 +23,9 @@ void main() {
float id = float(gl_InstanceID);
float sampleY = floor(id / dataTextureSize);
float sampleX = id - sampleY * dataTextureSize;
vec2 antDataUV = (vec2(sampleX, sampleY) + 0.5) / dataTextureSize;
vec4 dataSample = texture(tData, vec2(sampleX, sampleY) / dataTextureSize);
vec4 dataSample = texture(tData, antDataUV);
vec2 offset = dataSample.xy;
vec2 rotatedPosition = rotate(position.xy, -dataSample.z + PI * 0.5);

View file

@ -25,6 +25,10 @@ void main() {
isHome = 1;
} else if (drawMode == 3.) {
isObstacle = 1;
} else if (drawMode == 4.) {
isFood = 0;
isHome = 0;
isObstacle = 0;
}
}