Update GUI
This commit is contained in:
parent
a3c03cafef
commit
c84a3b46b7
15 changed files with 60 additions and 52 deletions
|
|
@ -15,10 +15,6 @@ If an ant senses the desirable pheromones nearby, then it turns to the direction
|
|||
It is important to prevent ants from following pheromone trails left by those ants who wandered too far from home or a food source. Each individual ant has an inventory for storing pheromones. Each time an ant leaves a pheromone marker anywhere on the map a small portion of the stored pheromones is used. And each time it picks up food or reaches home its inventory gets fully refilled.
|
||||
|
||||
Pheromone trails left by ants evaporate and diffuse over time.
|
||||
|
||||
## Compute pipeline overview
|
||||
|
||||
TODO
|
||||
|
||||
## References
|
||||
|
||||
|
|
|
|||
43
src/App.ts
43
src/App.ts
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
export default {
|
||||
worldSize: 1024,
|
||||
antsCount: 64 ** 2,
|
||||
antsCount: 12,
|
||||
simulationStepsPerSecond: 60,
|
||||
scentThreshold: 0.01,
|
||||
scentFadeOutFactor: 0.998,
|
||||
|
|
|
|||
29
src/GUI.ts
29
src/GUI.ts
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ export default class AntsComputeScene extends AbstractScene {
|
|||
|
||||
}
|
||||
|
||||
public update(deltaTime: number) {
|
||||
public update() {
|
||||
this.material.uniforms.uTime.value = performance.now();
|
||||
}
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ export default class AntsDiscretizeScene extends AbstractScene {
|
|||
|
||||
}
|
||||
|
||||
public update(deltaTime: number) {
|
||||
public update() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ export default class DrawScene extends AbstractScene {
|
|||
|
||||
}
|
||||
|
||||
public update(deltaTime: number) {
|
||||
public update() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ export default class WorldBlurScene extends AbstractScene {
|
|||
|
||||
}
|
||||
|
||||
public update(deltaTime: number) {
|
||||
public update() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ export default class WorldComputeScene extends AbstractScene {
|
|||
|
||||
}
|
||||
|
||||
public update(deltaTime: number) {
|
||||
public update() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ void main() {
|
|||
isHome = 1;
|
||||
} else if (drawMode == 3.) {
|
||||
isObstacle = 1;
|
||||
} else if (drawMode == 4.) {
|
||||
isFood = 0;
|
||||
isHome = 0;
|
||||
isObstacle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue