ConcentricParticles.java 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. package org.example;
  2. import ddf.minim.AudioInput;
  3. import ddf.minim.Minim;
  4. import ddf.minim.analysis.FFT;
  5. import processing.core.PApplet;
  6. import processing.core.PGraphics;
  7. import processing.core.PVector;
  8. import java.awt.*;
  9. import java.util.ArrayList;
  10. public class ConcentricParticles extends PApplet {
  11. Attractor att = new Attractor(new PVector(0, 0));
  12. float[] bgColor;
  13. float[] strokeColor;
  14. ArrayList<ArrayList<Particle>> cPoints = new ArrayList<ArrayList<Particle>>();
  15. ArrayList<Particle> points = new ArrayList<Particle>();
  16. int PARTICLE_MODE = 0;
  17. int DEFORM_MODE = 1;
  18. int mode = PARTICLE_MODE;
  19. int dir = 1;
  20. boolean reform = true;
  21. int margin = 25;
  22. float maxD;
  23. PGraphics pg;
  24. public void settings() {
  25. size(900, 900, P3D);
  26. }
  27. public void setup() {
  28. colorMode(HSB, 360, 100, 100, 100);
  29. pg = createGraphics(1080, 1080, P3D);
  30. pg.smooth(8);
  31. pg.beginDraw();
  32. pg.colorMode(HSB, 360, 100, 100, 100);
  33. pg.strokeWeight(mode == PARTICLE_MODE ? 3 : 2);
  34. bgColor = new float[]{250f,100f,10f};
  35. pg.blendMode(ADD);
  36. cursor(ARROW);
  37. pg.background(bgColor[0],bgColor[1],bgColor[2]);
  38. pg.noFill();
  39. pg.endDraw();
  40. int pixPerSegment = 5;
  41. maxD = sqrt(pg.width * pg.width + pg.height * pg.height);
  42. float baseHue = 200; // random(0, 280);
  43. for (int r = 440; r >= 10; r -= 10) {
  44. ArrayList<Particle> list = circlePoints(pg.width / 2, pg.height / 2, r, pixPerSegment);
  45. for (Particle p : list) {
  46. p.c = new float[]{baseHue + 80.0f * r / 440f, 60f, 100f}; //85, 100);
  47. }
  48. cPoints.add(list);
  49. points.addAll(list);
  50. }
  51. }
  52. public void draw() {
  53. PVector mouse = new PVector(map(mouseX, 0, width, 0, pg.width), map(mouseY, 0, height, 0, pg.height));
  54. att.pos = mouse;
  55. int button = 0;
  56. if (mousePressed) {
  57. button = mouseButton;
  58. }
  59. pg.beginDraw();
  60. pg.background(bgColor[0],bgColor[1],bgColor[2]);
  61. if (mode == PARTICLE_MODE) {
  62. if (mousePressed && mouseButton == LEFT) {
  63. button = 1;
  64. } else if (mousePressed && mouseButton == RIGHT) {
  65. button = -1;
  66. }
  67. for (Particle p : points) {
  68. PVector f = att.calcForce(p, button);
  69. f.mult(10);
  70. p.acc.add(f);
  71. p.update();
  72. pg.stroke(p.c[0],p.c[1],p.c[2]);
  73. pg.point(p.x, p.y);
  74. }
  75. } else if (mode == DEFORM_MODE) {
  76. switch(button) {
  77. case LEFT:
  78. deform(points, true);
  79. break;
  80. case RIGHT:
  81. deform(points, false);
  82. break;
  83. case CENTER:
  84. deformRadial(points);
  85. break;
  86. default:
  87. break;
  88. }
  89. for (Particle p : points) {
  90. p.update();
  91. pg.stroke(p.c[0],p.c[1],p.c[2]);
  92. pg.point(p.x, p.y);
  93. }
  94. }
  95. pg.fill(0, 100, 100, 100);
  96. pg.noStroke();
  97. pg.ellipse(mouse.x, mouse.y, 6f,6f);
  98. pg.noFill();
  99. pg.endDraw();
  100. image(pg, 0, 0, width, height);
  101. //println(frameCount / 60);
  102. println(frameRate);
  103. }
  104. @Override
  105. public void keyPressed() {
  106. if (key == CODED) {
  107. if (keyCode == UP) {
  108. dir *= -1;
  109. }
  110. if (keyCode == DOWN) {
  111. mode = 1 - mode;
  112. }
  113. }
  114. }
  115. void deform(ArrayList<Particle> set, boolean attract) {
  116. Particle c = new Particle(map(mouseX, 0, width, 0, pg.width), map(mouseY, 0, height, 0, pg.height)); // new Particle(width / 2, height / 2);
  117. float maxDiagonal = getMaxDist(c, set);
  118. for (Particle p : set) {
  119. float d = dist(p.x, p.y, c.x, c.y);
  120. float dFactor = attract ? 1 - 0.25f * pow(1 - d / maxDiagonal, 4) : 1 + 0.25f * pow(1 - d / maxDiagonal, 4);
  121. Particle temp = p.copy();
  122. temp.sub(c);
  123. temp.mult(dFactor);
  124. temp.add(c);
  125. p.x = temp.x;
  126. p.y = temp.y;
  127. }
  128. }
  129. void deformRadial(ArrayList<Particle> set) {
  130. Particle c = new Particle(map(mouseX, 0, width, 0, pg.width), map(mouseY, 0, height, 0, pg.height));
  131. float maxDiagonal = getMaxDist(c, set);
  132. for (Particle p : set) {
  133. float d = dist(p.x, p.y, c.x, c.y);
  134. float dFactor = pow(1 - d / maxDiagonal, 2.5f);
  135. rotateWithRespectTo(p, c, dir * dFactor * PI / 16);
  136. }
  137. }
  138. float getMaxDist(Particle p, ArrayList<Particle> set) {
  139. if (set.isEmpty()) {
  140. return 0;
  141. }
  142. float maxDistSq = Float.MIN_VALUE;
  143. for (Particle v : set) {
  144. float dSq = v.copy().sub(p).magSq();
  145. if (dSq > maxDistSq) {
  146. maxDistSq = dSq;
  147. }
  148. }
  149. return sqrt(maxDistSq);
  150. }
  151. void rotateWithRespectTo(Particle p, Particle v, float angle) {
  152. p.sub(v);
  153. p.rotate(angle);
  154. p.add(v);
  155. }
  156. void rotateWithRespectTo(PVector p, PVector v, float angle) {
  157. p.sub(v);
  158. p.rotate(angle);
  159. p.add(v);
  160. }
  161. ArrayList<Particle> linePoints(float x1, float y1, float x2, float y2, int pixPerSegment) {
  162. float d = dist(x1, y1, x2, y2);
  163. Particle a = new Particle(x1, y1);
  164. Particle b = new Particle(x2, y2);
  165. Particle diff = (Particle) b.copy().sub(a).normalize().mult(pixPerSegment);
  166. int n = (int)(d / pixPerSegment);
  167. ArrayList<Particle> points = new ArrayList<Particle>();
  168. for (int i = 0; i <= n; i++) {
  169. points.add((Particle) a.copy().add(diff.copy().mult(i)));
  170. }
  171. return points;
  172. }
  173. ArrayList<Particle> circlePoints(float x, float y, float r, int pixPerSegment) {
  174. float c = 2 * PI * r;
  175. int n = (int) (c / pixPerSegment);
  176. float inc = 2 * PI / n;
  177. ArrayList<Particle> points = new ArrayList<Particle>();
  178. for (int i = 0; i < n; i++) {
  179. float angle = i * inc;
  180. points.add(new Particle(x + r * cos(angle), y + r * sin(angle)));
  181. }
  182. return points;
  183. }
  184. public static void main(String[] passedArgs) {
  185. String[] appletArgs = new String[] { "ConcentricParticlesx" };
  186. ConcentricParticles ms = new ConcentricParticles();
  187. PApplet.runSketch(appletArgs,ms);
  188. }
  189. class Particle extends PVector {
  190. PVector init;
  191. PVector v;
  192. float[] c;
  193. PVector pos;
  194. PVector vel;
  195. PVector acc;
  196. Particle(float x, float y) {
  197. this.pos = new PVector(x, y);
  198. this.vel = new PVector(0, 0);
  199. this.acc = new PVector(0, 0);
  200. this.x = x;
  201. this.y = y;
  202. this.init = new PVector(x, y);
  203. this.v = new PVector(0, 0);
  204. }
  205. void update() {
  206. if (mode == PARTICLE_MODE) {
  207. vel.add(acc);
  208. vel.limit(5);
  209. checkBounds();
  210. x += vel.x;
  211. y += vel.y;
  212. this.vel.mult(0.997f);
  213. acc.mult(0);
  214. }
  215. if (reform) {
  216. Particle curr = new Particle(x, y);
  217. curr.lerp(init, 0.005f);
  218. this.x = curr.x;
  219. this.y = curr.y;
  220. }
  221. }
  222. void checkBounds() {
  223. if (x < margin || x > pg.width - margin) {
  224. vel.x *= -1;
  225. }
  226. if (y < margin || y > pg.height - margin) {
  227. vel.y *= -1;
  228. }
  229. }
  230. public Particle copy() {
  231. Particle p = new Particle(x, y);
  232. p.init = this.init.copy();
  233. return p;
  234. }
  235. }
  236. class Attractor {
  237. PVector pos;
  238. boolean active;
  239. Attractor(PVector pos) {
  240. this.pos = pos;
  241. active = false;
  242. }
  243. PVector calcForce(PVector otherPos, int charge) {
  244. if (charge == 0) {
  245. return new PVector(0, 0);
  246. }
  247. PVector vec = charge == 1 ? pos.copy().sub(otherPos) : otherPos.copy().sub(pos);
  248. float magSq = vec.mag();
  249. return vec.mult(500.0f / magSq).limit(5);
  250. }
  251. void show() {
  252. fill(active ? color(0, 255, 0) : color(255, 0, 0));
  253. ellipse(pos.x, pos.y, 30, 30);
  254. }
  255. }
  256. }