Add pheromone settings to GUI
This commit is contained in:
parent
c84a3b46b7
commit
9ecb9f55aa
7 changed files with 24 additions and 22 deletions
|
|
@ -4,6 +4,8 @@ A simple ant colony GPU-accelerated simulation made with Three.js.
|
||||||
|
|
||||||
**[Live demo](https://vhawk.github.io/ants-simulation/)**
|
**[Live demo](https://vhawk.github.io/ants-simulation/)**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Rules
|
## 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.
|
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.
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,7 @@ export default new class App {
|
||||||
|
|
||||||
this.renderLoop(0);
|
this.renderLoop(0);
|
||||||
|
|
||||||
this.gui.on('antsCount', () => {
|
this.gui.on('reset', () => {
|
||||||
this.resetRenderer();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.gui.on('worldSize', () => {
|
|
||||||
this.resetRenderer();
|
this.resetRenderer();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -84,6 +80,7 @@ export default new class App {
|
||||||
const simStepsToDo = deltaTime / 1000 * Config.simulationStepsPerSecond;
|
const simStepsToDo = deltaTime / 1000 * Config.simulationStepsPerSecond;
|
||||||
|
|
||||||
this.queuedSimSteps += simStepsToDo;
|
this.queuedSimSteps += simStepsToDo;
|
||||||
|
this.queuedSimSteps = Math.min(this.queuedSimSteps, 10);
|
||||||
|
|
||||||
while (this.queuedSimSteps >= 1) {
|
while (this.queuedSimSteps >= 1) {
|
||||||
this.simulationStep();
|
this.simulationStep();
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@ export default {
|
||||||
antsCount: 12,
|
antsCount: 12,
|
||||||
simulationStepsPerSecond: 60,
|
simulationStepsPerSecond: 60,
|
||||||
scentThreshold: 0.01,
|
scentThreshold: 0.01,
|
||||||
scentFadeOutFactor: 0.998,
|
scentFadeOutFactor: 0.001,
|
||||||
scentBlurRadius: 0.1,
|
scentBlurRadius: 0.1,
|
||||||
scentMaxStorage: 1e6,
|
scentMaxStorage: 1e6,
|
||||||
scentPerMarker: 300,
|
scentPerMarker: 200,
|
||||||
|
scentMaxPerCell: 10,
|
||||||
antSpeed: 1,
|
antSpeed: 1,
|
||||||
antRotationAngle: Math.PI / 50,
|
antRotationAngle: Math.PI / 30,
|
||||||
brushRadius: 20,
|
brushRadius: 20,
|
||||||
};
|
};
|
||||||
21
src/GUI.ts
21
src/GUI.ts
|
|
@ -15,21 +15,22 @@ export default class GUI extends EventEmitter {
|
||||||
simFolder.add(Config, 'worldSize', 256, 4096)
|
simFolder.add(Config, 'worldSize', 256, 4096)
|
||||||
.name('World size')
|
.name('World size')
|
||||||
.step(1)
|
.step(1)
|
||||||
.onChange(() => {
|
.onChange(() => this.emit('reset'));
|
||||||
this.emit('worldSize');
|
|
||||||
});
|
|
||||||
simFolder.add(Config, 'antsCount', 0, 22)
|
simFolder.add(Config, 'antsCount', 0, 22)
|
||||||
.name('Ants count 2^')
|
.name('Ants count 2^')
|
||||||
.step(1)
|
.step(1)
|
||||||
.onChange(() => {
|
.onChange(() => this.emit('reset'));
|
||||||
this.emit('antsCount');
|
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)
|
simFolder.add(Config, 'simulationStepsPerSecond', 1, 500)
|
||||||
.name('Simulation steps per second')
|
.name('Simulation steps per second')
|
||||||
.step(1)
|
.step(1);
|
||||||
.onChange(() => {
|
|
||||||
this.emit('simulationStepsPerSecond');
|
|
||||||
});
|
|
||||||
|
|
||||||
const controlsFolder = this.gui.addFolder('Controls');
|
const controlsFolder = this.gui.addFolder('Controls');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,7 @@ export default class Renderer {
|
||||||
SCENT_BLUR_RADIUS: Renderer.convertNumberToFloatString(Config.scentBlurRadius),
|
SCENT_BLUR_RADIUS: Renderer.convertNumberToFloatString(Config.scentBlurRadius),
|
||||||
SCENT_MAX_STORAGE: Renderer.convertNumberToFloatString(Config.scentMaxStorage),
|
SCENT_MAX_STORAGE: Renderer.convertNumberToFloatString(Config.scentMaxStorage),
|
||||||
SCENT_PER_MARKER: Renderer.convertNumberToFloatString(Config.scentPerMarker),
|
SCENT_PER_MARKER: Renderer.convertNumberToFloatString(Config.scentPerMarker),
|
||||||
|
SCENT_MAX_PER_CELL: Renderer.convertNumberToFloatString(Config.scentMaxPerCell),
|
||||||
ANT_SPEED: Renderer.convertNumberToFloatString(Config.antSpeed),
|
ANT_SPEED: Renderer.convertNumberToFloatString(Config.antSpeed),
|
||||||
ANT_ROTATION_ANGLE: Renderer.convertNumberToFloatString(Config.antRotationAngle)
|
ANT_ROTATION_ANGLE: Renderer.convertNumberToFloatString(Config.antRotationAngle)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ void main() {
|
||||||
int isFood = cellData & 1;
|
int isFood = cellData & 1;
|
||||||
int isHome = (cellData & 2) >> 1;
|
int isHome = (cellData & 2) >> 1;
|
||||||
int isObstacle = (cellData & 4) >> 2;
|
int isObstacle = (cellData & 4) >> 2;
|
||||||
float scentToHome = min(10., lastState.y + discreteAnts.x);
|
float scentToHome = min(SCENT_MAX_PER_CELL, lastState.y + discreteAnts.x);
|
||||||
float scentToFood = min(10., lastState.z + discreteAnts.y);
|
float scentToFood = min(SCENT_MAX_PER_CELL, lastState.z + discreteAnts.y);
|
||||||
|
|
||||||
if (discreteAnts.z == 1.) {
|
if (discreteAnts.z == 1.) {
|
||||||
isFood = 0;
|
isFood = 0;
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ void main() {
|
||||||
vec4 s3 = texture(tWorld, vUv + vec2(-1, 1) * offset);
|
vec4 s3 = texture(tWorld, vUv + vec2(-1, 1) * offset);
|
||||||
vec4 s4 = 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 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. * SCENT_FADE_OUT_FACTOR;
|
float scentToFood = (s0.z + s1.z + s2.z + s3.z + s4.z) / 5. * (1. - SCENT_FADE_OUT_FACTOR);
|
||||||
|
|
||||||
FragColor = vec4(
|
FragColor = vec4(
|
||||||
s0.x,
|
s0.x,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue