mouse drag to move charges, D while dragging to delete charge, T to toggle showing text, up/down arrows to add/remove charges
A fork of base frag shader by connor
xxxxxxxxxx
const drag_radius = 10;
const MAX_CHARGES = 10; // replace in frag shader too
let show_text = true;
let equipotentialShader;
let lineGraphics;
let charges = [];
let selected_charge_index = -1;
let updateImage = true;
function setup() {
//createCanvas(400, 400, WEBGL);
createCanvas(windowWidth, windowHeight);
lineGraphics = createGraphics(width, height, WEBGL);
equipotentialShader = createShader(equipotentialShaderCode.vert, equipotentialShaderCode.frag);
lineGraphics.rectMode(CENTER);
lineGraphics.noStroke();
lineGraphics.fill(255);
charges.push(new Charge(3*width/4, height/2, -2));
charges.push(new Charge(width/4, height/2, 1));
lineGraphics.shader(equipotentialShader);
textSize(20);
textAlign(CENTER, CENTER);
equipotentialShader.setUniform("uResolution", [width, height]);
}
function draw() {
if (selected_charge_index > -1) {
charges[selected_charge_index].x += (mouseX - pmouseX);
charges[selected_charge_index].y += (mouseY - pmouseY);
updateImage = true;
}
if (updateImage) {
redrawImage();
updateImage = false;
}
}
function mousePressed() {
min_index = -1;
min_dist = Infinity;
for (let i = 0; i < charges.length; i++) {
let c = charges[i];
let dist = (c.x-mouseX)**2 + (c.y-mouseY)**2;
if (dist < min_dist) {
min_dist = dist;
min_index = i
}
}
if (min_dist < drag_radius*drag_radius) {
selected_charge_index = min_index;
}
}
function mouseReleased() {
selected_charge_index = -1;
updateImage = true;
}
function redrawImage() {
equipotentialShader.setUniform("uChargeList", createChargeUniform(charges));
lineGraphics.clear();
lineGraphics.rect(0,0,width, height);
background(255, 255, 200);
image(lineGraphics, 0, 0, width, height);
for (let c of charges) {
c.show()
}
}
function windowResized(){
resizeCanvas(windowWidth, windowHeight);
lineGraphics.resizeCanvas(width, height);
equipotentialShader.setUniform("uResolution", [width, height]);
updateImage = true;
}
function keyPressed() {
// print(keyCode)
switch (keyCode) {
case 84: // T
show_text = !show_text;
updateImage = true;
return;
case 38: // Up Arrow
if (charges.length < MAX_CHARGES) {
addRandomCharge()
}
updateImage = true;
return;
case 40: // Down Arrow
if (charges.length > 0) {
charges.pop();
}
updateImage = true;
return;
case 68: // D
if (selected_charge_index > -1) {
charges.splice(selected_charge_index, 1);
selected_charge_index = -1;
}
updateImage = true;
return;
}
}
function addRandomCharge() {
charges.push(new Charge(random(width), random(height), random([-3, -2, -1, 1, 2, 3])));
}
function createChargeUniform(charges) {
let result = [];
for (let i = 0; i < 10; i++) {
if (i < charges.length) {
let c = charges[i];
result.push(c.x, c.y, c.q);
} else result.push(0,0,0);
}
return result;
}
class Charge {
constructor(x, y, q) {
this.x = x;
this.y = y;
this.q = q;
}
show() {
strokeWeight(25);
if (this.q > 0) stroke(255, 0, 0);
else stroke(0,0,255);
point(this.x, this.y);
if(show_text) {
strokeWeight(5);
fill(255);
text("" + this.q + "C", this.x, this.y-25)
}
}
}