Add pheromone settings to GUI

This commit is contained in:
vHawk 2022-07-11 05:43:33 +03:00
parent c84a3b46b7
commit 9ecb9f55aa
7 changed files with 24 additions and 22 deletions

View file

@ -4,6 +4,8 @@ A simple ant colony GPU-accelerated simulation made with Three.js.
**[Live demo](https://vhawk.github.io/ants-simulation/)**
![ants collecting food](https://i.imgur.com/FeU3UvR.png)
## Rules
Ants can emit two types of pheromones: to-home pheromone and to-food pheromone. To-home pheromones are emitted by those ants searching for food and to-food pheromones are emitted by those carrying food. Ants searching for food are attracted to to-food pheromones, while ants searching for home are attracted to to-home pheromones.

View file

@ -34,11 +34,7 @@ export default new class App {
this.renderLoop(0);
this.gui.on('antsCount', () => {
this.resetRenderer();
});
this.gui.on('worldSize', () => {
this.gui.on('reset', () => {
this.resetRenderer();
});
}
@ -84,6 +80,7 @@ export default new class App {
const simStepsToDo = deltaTime / 1000 * Config.simulationStepsPerSecond;
this.queuedSimSteps += simStepsToDo;
this.queuedSimSteps = Math.min(this.queuedSimSteps, 10);
while (this.queuedSimSteps >= 1) {
this.simulationStep();

View file

@ -3,11 +3,12 @@ export default {
antsCount: 12,
simulationStepsPerSecond: 60,
scentThreshold: 0.01,
scentFadeOutFactor: 0.998,
scentFadeOutFactor: 0.001,
scentBlurRadius: 0.1,
scentMaxStorage: 1e6,
scentPerMarker: 300,
scentPerMarker: 200,
scentMaxPerCell: 10,
antSpeed: 1,
antRotationAngle: Math.PI / 50,
antRotationAngle: Math.PI / 30,
brushRadius: 20,
};

View file

@ -15,21 +15,22 @@ export default class GUI extends EventEmitter {
simFolder.add(Config, 'worldSize', 256, 4096)
.name('World size')
.step(1)
.onChange(() => {
this.emit('worldSize');
});
.onChange(() => this.emit('reset'));
simFolder.add(Config, 'antsCount', 0, 22)
.name('Ants count 2^')
.step(1)
.onChange(() => {
this.emit('antsCount');
});
.onChange(() => this.emit('reset'));
simFolder.add(Config, 'scentFadeOutFactor', 0, 0.01)
.name('Pheromone evaporation factor')
.step(0.0001)
.onChange(() => this.emit('reset'));
simFolder.add(Config, 'scentBlurRadius', 0, 0.5)
.name('Pheromone diffusion factor')
.step(0.01)
.onChange(() => this.emit('reset'));
simFolder.add(Config, 'simulationStepsPerSecond', 1, 500)
.name('Simulation steps per second')
.step(1)
.onChange(() => {
this.emit('simulationStepsPerSecond');
});
.step(1);
const controlsFolder = this.gui.addFolder('Controls');

View file

@ -133,6 +133,7 @@ export default class Renderer {
SCENT_BLUR_RADIUS: Renderer.convertNumberToFloatString(Config.scentBlurRadius),
SCENT_MAX_STORAGE: Renderer.convertNumberToFloatString(Config.scentMaxStorage),
SCENT_PER_MARKER: Renderer.convertNumberToFloatString(Config.scentPerMarker),
SCENT_MAX_PER_CELL: Renderer.convertNumberToFloatString(Config.scentMaxPerCell),
ANT_SPEED: Renderer.convertNumberToFloatString(Config.antSpeed),
ANT_ROTATION_ANGLE: Renderer.convertNumberToFloatString(Config.antRotationAngle)
};

View file

@ -16,8 +16,8 @@ void main() {
int isFood = cellData & 1;
int isHome = (cellData & 2) >> 1;
int isObstacle = (cellData & 4) >> 2;
float scentToHome = min(10., lastState.y + discreteAnts.x);
float scentToFood = min(10., lastState.z + discreteAnts.y);
float scentToHome = min(SCENT_MAX_PER_CELL, lastState.y + discreteAnts.x);
float scentToFood = min(SCENT_MAX_PER_CELL, lastState.z + discreteAnts.y);
if (discreteAnts.z == 1.) {
isFood = 0;

View file

@ -16,8 +16,8 @@ void main() {
vec4 s3 = texture(tWorld, vUv + vec2(-1, 1) * offset);
vec4 s4 = texture(tWorld, vUv + vec2(1, -1) * offset);
float scentToHome = (s0.y + s1.y + s2.y + s3.y + s4.y) / 5. * SCENT_FADE_OUT_FACTOR;
float scentToFood = (s0.z + s1.z + s2.z + s3.z + s4.z) / 5. * SCENT_FADE_OUT_FACTOR;
float scentToHome = (s0.y + s1.y + s2.y + s3.y + s4.y) / 5. * (1. - SCENT_FADE_OUT_FACTOR);
float scentToFood = (s0.z + s1.z + s2.z + s3.z + s4.z) / 5. * (1. - SCENT_FADE_OUT_FACTOR);
FragColor = vec4(
s0.x,