/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.JCdFutuGJyw/rev.458
*
* authors:
* alejandro robles
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
//By: Alejandro Robles //
//Version 2.1 //
//Date Started: 2/8/2012 //
//Discription: This is a physics engine //
//which I have been working on for a couple //
//of months now on my free time, enjoy. //
import processing.opengl.*;
int width = 300;
int height = 300;
/******spec*******/
int maximum = 50;
float friction = .99;
float gy = 1;
float gx = 0;
float tstep = .1;
/*****************/
physics p1 = new physics(maximum);
float distance;
int s;
int[] sel = new int[maximum+1];
int[] stop = new int[maximum+1];
void setup() {
size(width, height, P2D);
for (int n = 0; n <= maximum; n++) {
sel[n] = 0;
stop[n] = 0;
}
smooth();
strokeWeight(1);
}
void draw() {
background(255);
for (int n = 0; n < p1.count; n++) {
for (int m = n+1; m < p1.count; m++) {
p1.atract_particles(n, m, 6, 0, .4);
}
if (n < p1.count-1) {
p1.atract_particles_2d(n, n+1, 2, 0, 0);
}
if (n < p1.count-2) {
p1.atract_particles_2d(n, n+2, 2, 0, 0);
}
p1.update(n, friction, gx, gy);
p1.bounds(n, 0, width, 0, height);
//sel[n] = 0;
}
for (int n = 0; n < p1.count; n++) {
fill(255*n/(p1.count), 255-(2*abs(128 - (255*n/(p1.count)))), 255 - 255*n/(p1.count), 255);
stroke(0);
ellipse((float)p1.obj[n][0], (float)p1.obj[n][1], 2*(float)p1.obj[n][4], 2*(float)p1.obj[n][4]);
if (n < p1.count-1) {
line((float)p1.obj[n][0], (float)p1.obj[n][1], (float)p1.obj[n+1][0], (float)p1.obj[n+1][1]);
}
if (n < p1.count-2) {
line((float)p1.obj[n][0], (float)p1.obj[n][1], (float)p1.obj[n+2][0], (float)p1.obj[n+2][1]);
}
}
if (p1.count < maximum) {
if (mousePressed) {
double[] info = {
mouseX, mouseY, (mouseX - pmouseX)/tstep, (mouseY - pmouseY)/tstep, 2, 100, 0
};
p1.spawn(info);
}
}
else {
//sel[n] = 0;
for (int n = 0; n < p1.count; n++) {
/*/
if (mousePressed) {
distance = dist((float)p1.obj[n][0], (float)p1.obj[n][1], mouseX, mouseY);
if (distance < 30) {
p1.obj[n][2] = (mouseX - pmouseX)/tstep;
p1.obj[n][3] = (mouseY - pmouseY)/tstep;
}
}
/*/
particle_select(n);
}
}
print(frameRate);
print(", ");
println(p1.count);
}
void particle_select(int n) {
if (mousePressed) {
if ((dist(mouseX, mouseY, (float)p1.obj[n][0], (float)p1.obj[n][1]) < p1.obj[n][4]) && (s == 0) || (sel[n] == 1)) {
s = 1;
sel[n] = 1;
if (keyPressed) {
if (key == ' ')
p1.obj[n][6] = 1;
}
/*/
p1.obj[n][0] = mouseX;
p1.obj[n][1] = mouseY;
p1.obj[n][2] = (mouseX - pmouseX)/tstep;
p1.obj[n][3] = (mouseY - pmouseY)/tstep;
/*/
p1.obj[n][2] += (mouseX - p1.obj[n][0]);
p1.obj[n][3] += (mouseY - p1.obj[n][1]);
stroke(150, 150, 0, 100);
line((float)p1.obj[n][0], (float)p1.obj[n][1], mouseX, mouseY);
//if(keyTyped == true) {
// obj[n][6] = 1;
// }
}
}
else {
s = 0;
sel[n] = 0;
}
}
int r = 0;
void keyTyped() {
if (key == ENTER) {
r++;
gx = sin(r*PI/2);
gy = cos(r*PI/2);
}
}
class physics {
int count = 0;
int maximum;
double[][] obj;
physics(int max) {
maximum = max;
obj = new double[maximum+1][7];
}
void update(int n, float f, float gx, float gy) {
if (obj[n][6] == 0) {
obj[n][0] += obj[n][2]*tstep;
obj[n][1] += obj[n][3]*tstep;
obj[n][2] += gx;
obj[n][3] += gy;
obj[n][2] *= f;
obj[n][3] *= f;
}
else {
obj[n][2] = 0;
obj[n][3] = 0;
}
}
void spawn(double[] info) {
if (count < maximum) {
for (int n = 0; n <= 6; n++) {
obj[count][n] = info[n];
}
count++;
}
}
double atract(float fconst, float damper, double delta, double vdelta) {
return fconst / (delta*delta) - damper*vdelta/delta;
}
double grav(float gconst, float damper, double m1, double m2, double delta, double vdelta) {
return (((gconst*m1*m2)/(delta*delta)) - damper*vdelta);
}
double spring(float sconst, float damper, float r, double delta, double vdelta) {
return -((sconst*(r - delta)) + damper*vdelta);
}
double soft(float econst, float damper, double r1, double r2, double delta, double vdelta) {
return (-(econst*(r1 + r2 - delta)) - damper*vdelta);
}
double surf_tens(float tconst, float visc, double r, double delta, double vdelta) {
return ((tconst/((r - delta)*(r - delta))) - visc*vdelta);
}
double particle_collide(float elasticity, double m1, double m2, double vdelta) {
return ((m1-m2)/(m1+m2))*elasticity*vdelta;
}
void bounds(int n, int xs, int xe, int ys, int ye) {
if (obj[n][0] < xs + obj[n][4]) {
obj[n][0] = xs + obj[n][4];
obj[n][2] *= -1;
}
if (obj[n][0] > xe - obj[n][4]) {
obj[n][0] = xe - obj[n][4];
obj[n][2] *= -1;
}
if (obj[n][1] < ys + obj[n][4]) {
obj[n][1] = ys + obj[n][4];
obj[n][3] *= -1;
}
if (obj[n][1] > ye - obj[n][4]) {
obj[n][1] = ye - obj[n][4];
obj[n][3] *= -1;
}
}
void inverse_bounds(int n, int xs, int xe, int ys, int ye) {
/*/
if (obj[n][0] > xs - obj[n][4])&& {
obj[n][0] = xs + obj[n][4];
obj[n][2] *= -1;
}
if (obj[n][0] < xe + obj[n][4]) {
obj[n][0] = xe - obj[n][4];
obj[n][2] *= -1;
}
if (obj[n][1] < ys + obj[n][4]) {
obj[n][1] = ys + obj[n][4];
obj[n][3] *= -1;
}
if (obj[n][1] > ye - obj[n][4]) {
obj[n][1] = ye - obj[n][4];
obj[n][3] *= -1;
}
/*/
}
void atract_particles_2d(int p1, int p2, float fconst, float min, float damp) {
double delta, dnx, dny, force, vdelta;
dnx = obj[p2][0] - obj[p1][0];
dny = obj[p2][1] - obj[p1][1];
delta = mag((float)dnx, (float)dny);
force = 0;
if (delta == 0) {
delta = .0001;
obj[p1][0] += .0001;
}
dnx /= delta;
dny /= delta;
vdelta = (dnx*obj[p1][2]) + (dny*obj[p1][3]) - (dnx*obj[p2][2]) - (dny*obj[p2][3]);
if (delta < min) {
delta = min;
}
force = spring(5, .5, 10, delta, vdelta);
obj[p2][2] -= (dnx * force);
obj[p2][3] -= (dny * force);
obj[p1][2] += (dnx * force);
obj[p1][3] += (dny * force);
}
void atract_particles(int p1, int p2, float fconst, float min, float damp) {
double delta, dnx, dny, force, vdelta;
dnx = obj[p2][0] - obj[p1][0];
dny = obj[p2][1] - obj[p1][1];
delta = mag((float)dnx, (float)dny);
force = 0;
if (delta == 0) {
delta = .0001;
obj[p1][0] += .0001;
}
dnx /= delta;
dny /= delta;
vdelta = (dnx*obj[p1][2]) + (dny*obj[p1][3]) - (dnx*obj[p2][2]) - (dny*obj[p2][3]);
if (delta < min) {
delta = min;
}
if (delta < (obj[p1][4] + obj[p2][4])) {
force = soft(fconst, damp, obj[p1][4], obj[p2][4], delta, vdelta);
}
obj[p2][2] -= (dnx * force);
obj[p2][3] -= (dny * force);
obj[p1][2] += (dnx * force);
obj[p1][3] += (dny * force);
}
}