-
Professional Air Guitarist
Verlet Integration (aka Ragdoll Physics) converted to Processing
Didn't get much (any =\) love last time I posted this. I've done a lot since and maybe more will be interested. For those who don't know, Processing is the upcomming easy-to-use Java (which is what AS is based on) writing environment/complier. If you don't have it please check out the site and download the FREE beta. It will only work on the latest version.
Why Processing? The power. Java may be a tad harder to learn, but the reward is much greater. Running a similar script in Flash ran slowly for me on my 1.5ghz Mac, but in Processing it soars at 60 fps. Nuff said, here it is:
Code:
Point[] pL;
Segment[] sL;
Circle[] cL;
void setup() {
size(600, 400);
framerate(60);
stroke(20, 60, 40);
ellipseMode(CENTER);
noSmooth();
noFill();
pL = new Point[14];
pL[0] = new Point(0, 0, 0);
pL[1] = new Point(50, 0, 0);
pL[2] = new Point(50, 50, 0);
pL[3] = new Point(0, 50, 0);
pL[4] = new Point(0, 100, 25);
pL[5] = new Point(0, 150, 25);
pL[6] = new Point(0, 200, 25);
pL[7] = new Point(0, 250, 25);
pL[8] = new Point(0, 300, 25);
pL[9] = new Point(0, 350, 25);
pL[10] = new Point(0, 400, 25);
pL[11] = new Point(0, 450, 25);
pL[12] = new Point(0, 500, 25);
pL[13] = new Point(550, 350, 50);
sL = new Segment[14];
sL[0] = new Segment(0, 1, true);
sL[1] = new Segment(1, 2, true);
sL[2] = new Segment(2, 3, true);
sL[3] = new Segment(3, 0, true);
sL[4] = new Segment(0, 2, false);
sL[5] = new Segment(1, 3, false);
sL[6] = new Segment(4, 5, true);
sL[7] = new Segment(5, 6, true);
sL[8] = new Segment(6, 7, true);
sL[9] = new Segment(7, 8, true);
sL[10] = new Segment(8, 9, true);
sL[11] = new Segment(9, 10, true);
sL[12] = new Segment(10, 11, true);
sL[13] = new Segment(11, 12, true);
cL = new Circle[1];
cL[0] = new Circle(400, 250, 50);
}
float initX = 0;
float initY = 0;
float drag = .95;
float grav = .5;
float a0x = 200;
float a0y = 100;
float a1x = 400;
float a1y = 100;
float x0, y0, x1, y1, cx, cy, cr, p0r, p1r, a, px, py, dx, dy, d0, d1, d;
int p0, p1;
int pD = -1;
float getDistance(int p0, int p1) {
return sqrt(sq(pL[p0].x-pL[p1].x)+sq(pL[p0].y-pL[p1].y));
}
void draw() {
background(120, 140, 100);
if (mousePressed && keyPressed) {
if (keyCode == SHIFT) {
pL[0].x += (mouseX-pL[0].x)/25;
pL[0].y += (mouseY-pL[0].y)/25;
}
if (pD != -1) {
pL[pD].x += (mouseX-pL[pD].x)/25;
pL[pD].y += (mouseY-pL[pD].y)/25;
if (pD == 4) {
a0x = pL[pD].x;
a0y = pL[pD].y;
}
if (pD == 12) {
a1x = pL[pD].x;
a1y = pL[pD].y;
}
}
}
pL[4].x = a0x;
pL[4].y = a0y;
pL[12].x = a1x;
pL[12].y = a1y;
verlet();
segmentCollide();
pointCollide();
render();
}
void mousePressed() {
if (keyPressed && keyCode == CONTROL) {
pD = -1;
for (int i=0; i<pL.length; i++) {
if (sqrt(sq(pL[i].x-mouseX)+sq(pL[i].y-mouseY)) < pL[i].r) {
pD = i;
break;
}
}
}
}
void mouseReleased() {
pD = -1;
}
void verlet() {
for (int i=0; i<pL.length; i++) {
px = pL[i].oX;
py = pL[i].oY;
pL[i].oX = pL[i].x;
pL[i].oY = pL[i].y;
pL[i].x += drag*(pL[i].oX-px);
pL[i].y += drag*(pL[i].oY-py)+grav;
}
for (int i=0; i<sL.length; i++) {
p0 = int(sL[i].p0);
p1 = int(sL[i].p1);
dx = pL[p0].x-pL[p1].x;
dy = pL[p0].y-pL[p1].y;
d = getDistance(p0, p1);
d0 = d1 = (d-sL[i].rL)/d;
d0 *= 0.5;
d1 *= 0.5;
pL[p0].x -= dx*d0;
pL[p0].y -= dy*d0;
pL[p1].x += dx*d1;
pL[p1].y += dy*d1;
}
}
void segmentCollide() {
for (int i=0; i<sL.length; i++) {
if (!sL[i].collide) {
continue;
}
p0 = int(sL[i].p0);
p1 = int(sL[i].p1);
p0r = pL[p0].r;
p1r = pL[p1].r;
//Segment vs Circle
for (int j=0; j<cL.length; j++) {
cx = cL[j].x;
cy = cL[j].y;
cr = cL[j].r;
x0 = pL[p0].x;
y0 = pL[p0].y;
x1 = pL[p1].x;
y1 = pL[p1].y;
a = ((x1-x0)*(cx-x0)+(y1-y0)*(cy-y0))/(sq(x1-x0)+sq(y1-y0));
a = a<0?0:a;
a = a>1?1:a;
px = pL[p0].x+(pL[p1].x-pL[p0].x)*a;
py = pL[p0].y+(pL[p1].y-pL[p0].y)*a;
d = sqrt(sq(px-cx)+sq(py-cy));
if (d < cr) {
d = 2*(cr-d);
dx = (px-cx)/cr;
dy = (py-cy)/cr;
pL[p0].x += d*dx*(1-a);
pL[p0].y += d*dy*(1-a);
pL[p1].x += d*dx*a;
pL[p1].y += d*dy*a;
}
}
//Segment vs Point
for (int j=0; j<pL.length; j++) {
if (j == p0 || j == p1) {
continue;
}
cx = pL[j].x;
cy = pL[j].y;
cr = pL[j].r;
x0 = pL[p0].x;
y0 = pL[p0].y;
x1 = pL[p1].x;
y1 = pL[p1].y;
a = ((x1-x0)*(cx-x0)+(y1-y0)*(cy-y0))/(sq(x1-x0)+sq(y1-y0));
a = a<0?0:a;
a = a>1?1:a;
px = pL[p0].x+(pL[p1].x-pL[p0].x)*a;
py = pL[p0].y+(pL[p1].y-pL[p0].y)*a;
d = sqrt(sq(px-cx)+sq(py-cy));
if (d < cr) {
d = (cr-d);
dx = (px-cx)/cr;
dy = (py-cy)/cr;
pL[j].x -= d*dx;
pL[j].y -= d*dy;
pL[p0].x += d*dx*(1-a);
pL[p0].y += d*dy*(1-a);
pL[p1].x += d*dx*a;
pL[p1].y += d*dy*a;
}
}
}
}
void pointCollide() {
for (int i=0; i<pL.length; i++) {
p0r = pL[i].r;
//Point vs Circle
for (int j=0; j<cL.length; j++) {
cx = cL[j].x;
cy = cL[j].y;
cr = cL[j].r+p0r;
px = pL[i].x;
py = pL[i].y;
d = sqrt(sq(px-cx)+sq(py-cy));
if (d < cr) {
d = (cr-d);
dx = (px-cx)/cr;
dy = (py-cy)/cr;
pL[i].x += d*dx;
pL[i].y += d*dy;
}
}
//Point vs Point
for (int j=0; j<pL.length; j++) {
if (j == i) {
continue;
}
cx = pL[j].x;
cy = pL[j].y;
cr = pL[j].r+p0r;
px = pL[i].x;
py = pL[i].y;
d = sqrt(sq(px-cx)+sq(py-cy));
if (d < cr) {
d = (cr-d);
dx = (px-cx)/cr;
dy = (py-cy)/cr;
pL[j].x -= d*dx;
pL[j].y -= d*dy;
pL[i].x += d*dx;
pL[i].y += d*dy;
}
}
if (pL[i].x < p0r) {
pL[i].x = p0r;
}
else if (pL[i].x > width-p0r) {
pL[i].x = width-p0r;
}
if (pL[i].y < p0r) {
pL[i].y = p0r;
}
else if (pL[i].y > height-p0r) {
pL[i].y = height-p0r;
}
}
}
void render() {
for (int i=0; i<cL.length; i++) {
ellipse(cL[i].x, cL[i].y, cL[i].r*2, cL[i].r*2);
}
for (int i=0; i<sL.length; i++) {
p0 = int(sL[i].p0);
p1 = int(sL[i].p1);
line(pL[p0].x, pL[p0].y, pL[p1].x, pL[p1].y);
}
for (int i=0; i<pL.length; i++) {
if (pL[i].r > 0) {
ellipse(pL[i].x, pL[i].y, 2*pL[i].r, 2*pL[i].r);
}
}
}
class Point {
float x, y, oX, oY, r;
Point (float Tx, float Ty, float Tr) {
x = Tx+initX;
y = Ty+initY;
oX = x;
oY = y;
r = Tr;
}
}
class Segment {
int p0, p1;
float rL;
boolean collide, fillCollide;
Segment (int Tp0, int Tp1, boolean Tcollide) {
p0 = int(Tp0);
p1 = int(Tp1);
rL = getDistance(p0, p1);
collide = Tcollide;
}
}
class Circle {
float x, y, r;
Circle (float Tx, float Ty, float Tr) {
x = Tx;
y = Ty;
r = Tr;
}
}
EDIT: (For those who don't want to download Processing click HERE) To drag the cube press shift and press and hold your mouse. To drag any of the balls (except the large static one) press control and press and hold your mouse. The balls on the ends are anchors and will remain where they were last dragged. Have fun!
EDIT2: Added a circle to throw around too.
Last edited by Frag; 07-11-2005 at 09:45 AM.
-
n00b
why not show us an example of it running instead? I think that would be more interesting than looking at a bunch of code...
-
Professional Air Guitarist
Yea thought about that after I posted =p
I added a link to an example at the bottom of the first post.
-
Senior Member
Just wondering why you post in the Flash board. Isnt there similar Java boards where you could probably get some replies from the people who understand the Java code?
-
-
Professional Air Guitarist
I'm not really asking for help but rather trying to sway people to concider Java as another tool to learn and show off this cool doohickey And besides, this is more like an extention of Raigan's Flash work just in a different language
-
I downloaded the beta, I'm gonna try to learn this cause I'm tired of flash slowing down on simple stuff all the time
-
Wow, very chewing-gum-ish*. Very nice, i like i like.
*(dunno, a random word popped while playing with it...I mean the rag doll physics thingy man iam sounding weird)
-
Style Through Simplicity
Yea, im interested in learning java. m going to download this. The thing you showed wouldnt work for me...it just froe all the time, and wouldnt move when i tried to drag them. Then it would suddenly just jerk and move them all as if it was lagging very badly.
Ali
-
....he's amazing!!!
Originally Posted by tonypa
Just wondering why you post in the Flash board. Isnt there similar Java boards where you could probably get some replies from the people who understand the Java code?
Actually, IIRC, processing code is a lot more similar to javascript/actionscript than java, but it ports to java code to make it much faster
I think I'm gonna start learning it myself. Though the webpage isn't working at the moment.
-
Senior Member
It looks very very cool, great physics!
All very interesting .
I see you've made quite a following....
Nice!
-
383,890,620 polygons
Originally Posted by The_Mercenary
I downloaded the beta, I'm gonna try to learn this cause I'm tired of flash slowing down on simple stuff all the time
yeah right! that's the trick. to raise the limits on a slow system (like flash) and still come up with something playable and fast ...
some can handle it, some cannot - that's why we *love* flash
[edit]
nice example, though.
[/edit]
nGFX
Last edited by nGFX; 07-11-2005 at 01:28 PM.
-
-= phil =-
Hey peoples!
I just had to post to this one
Looks good there Frag. I remember your work with this before. Inspired me to work on my own verlet intergration scheme for flash (sorry, don't have the example up right now, but had cirlces running at a solid 60 fps. Stopped because I felt like it).
Anyways, it's interesting that you are talking about Java. I did not really look at this "Processing" business, but my opinion is why pay for something like that when you can just learn to use Java and do the graphics on your own. For what you are doing Frag, the graphics are not that hard (I could even help you if you wanted).
Again your work is quite nice, though your code scares the heck out of me... I suppose you are an anti-conformist
lesli_felix: Actually, IIRC, processing code is a lot more similar to javascript/actionscript than java, but it ports to java code to make it much faster
Um... what Frag posted is indeed Java Code... so I don't think anything is being ported here. It just looks a lot like Javascript/Actionscript because those language definitions are very similar to the Java language syntax def.
And finallly... I NEVER NEVER thought I would hear someone say they moved to Java for SPEED. LOL. Java is indeed more powerful than Flash because it is considered a Programming Language rather than a Scripting Language (let's just leave it there). But, if you really wanted speed, you should be moving to C++ or even C# (much much nicer than C++), since Java is about 5 times slower than C++. Alright enough said.
I did not want to get off topic on a flash board, but just putting in my two cents.
-
....he's amazing!!!
Originally Posted by d3s_inc
Um... what Frag posted is indeed Java Code... so I don't think anything is being ported here. It just looks a lot like Javascript/Actionscript because those language definitions are very similar to the Java language syntax def.
Sorry, maybe I'm I missing something here..this is what it says on the processing website:
Exporting creates a version of the sketch that can run within a Web browser. When code is exported from Processing it is changed into Java code and then compiled as a Java Applet.
Originally Posted by d3s_inc
And finallly... I NEVER NEVER thought I would hear someone say they moved to Java for SPEED. LOL. Java is indeed more powerful than Flash because it is considered a Programming Language rather than a Scripting Language (let's just leave it there). But, if you really wanted speed, you should be moving to C++ or even C# (much much nicer than C++), since Java is about 5 times slower than C++.
If you're talking about downloadable platform-specific applications, you're spot on. But from the perspective of somebody who develops web-based, platform independant apps and games, then C just isn't an option. Flash and java are where it's at.
-
Professional Air Guitarist
I actually tried getting into C and C++, but after a few days of researching the languages they looked so remotely different than AS (as apposed the clear relation with Java), I didn't have the will power to move that way. Was I wrong in saying Java was faster than Flash? Maybe it's a Mac thing
My point is, for the relative ease it was adjust to Java, I think it was well worth the time to gain the power.
EDIT: This is the start of a ragdoll I will eventually replace with my own body =) You need to have Processing to run it as I haven't uploaded an Applet left.
Code:
Point[] pL;
Segment[] sL;
Circle[] cL;
void setup() {
size(600, 400);
framerate(60);
stroke(20, 60, 40);
ellipseMode(CENTER);
noSmooth();
noFill();
pL = new Point[15];
pL[0] = new Point(0, 0, 20);
pL[1] = new Point(0, 35, 15);
pL[2] = new Point(0, 100, 15);
pL[3] = new Point(0, 150, 10);
pL[4] = new Point(0, 200, 5);
pL[5] = new Point(20, 200, 5);
pL[6] = new Point(0, 150, 10);
pL[7] = new Point(0, 200, 5);
pL[8] = new Point(20, 200, 5);
pL[9] = new Point(0, 75, 10);
pL[10] = new Point(0, 125, 5);
pL[11] = new Point(10, 125, 5);
pL[12] = new Point(0, 75, 10);
pL[13] = new Point(0, 125, 5);
pL[14] = new Point(10, 125, 5);
sL = new Segment[14];
sL[0] = new Segment(0, 1, true);
sL[1] = new Segment(1, 2, true);
sL[2] = new Segment(2, 3, true);
sL[3] = new Segment(3, 4, true);
sL[4] = new Segment(4, 5, true);
sL[5] = new Segment(2, 6, true);
sL[6] = new Segment(6, 7, true);
sL[7] = new Segment(7, 8, true);
sL[8] = new Segment(1, 9, true);
sL[9] = new Segment(9, 10, true);
sL[10] = new Segment(10, 11, true);
sL[11] = new Segment(1, 12, true);
sL[12] = new Segment(12, 13, true);
sL[13] = new Segment(13, 14, true);
cL = new Circle[3];
cL[0] = new Circle(500, 250, 50);
cL[1] = new Circle(200, 300, 25);
cL[2] = new Circle(300, 200, 75);
}
float initX = 0;
float initY = 0;
float drag = .98;
float grav = .1;
float a0x = 200;
float a0y = 100;
float a1x = 400;
float a1y = 100;
float x0, y0, x1, y1, cx, cy, cr, p0r, p1r, a, px, py, dx, dy, d0, d1, d;
int p0, p1;
int pD = -1;
float getDistance(int p0, int p1) {
return sqrt(sq(pL[p0].x-pL[p1].x)+sq(pL[p0].y-pL[p1].y));
}
void draw() {
background(120, 140, 100);
if (pD != -1) {
pL[pD].x += (mouseX-pL[pD].x)/25;
pL[pD].y += (mouseY-pL[pD].y)/25;
}
verlet();
segmentCollide(false);
pointCollide(false);
render();
}
void mousePressed() {
pD = -1;
for (int i=0; i<pL.length; i++) {
if (sqrt(sq(pL[i].x-mouseX)+sq(pL[i].y-mouseY)) < pL[i].r) {
pD = i;
break;
}
}
}
void mouseReleased() {
pD = -1;
}
void verlet() {
for (int i=0; i<pL.length; i++) {
px = pL[i].oX;
py = pL[i].oY;
pL[i].oX = pL[i].x;
pL[i].oY = pL[i].y;
pL[i].x += drag*(pL[i].oX-px);
pL[i].y += drag*(pL[i].oY-py)+grav;
}
for (int i=0; i<sL.length; i++) {
p0 = int(sL[i].p0);
p1 = int(sL[i].p1);
dx = pL[p0].x-pL[p1].x;
dy = pL[p0].y-pL[p1].y;
d = getDistance(p0, p1);
d0 = d1 = (d-sL[i].rL)/d;
d0 *= 0.5;
d1 *= 0.5;
pL[p0].x -= dx*d0;
pL[p0].y -= dy*d0;
pL[p1].x += dx*d1;
pL[p1].y += dy*d1;
}
}
void segmentCollide(boolean toPoints) {
for (int i=0; i<sL.length; i++) {
if (!sL[i].collide) {
continue;
}
p0 = int(sL[i].p0);
p1 = int(sL[i].p1);
p0r = pL[p0].r;
p1r = pL[p1].r;
//Segment vs Circle
for (int j=0; j<cL.length; j++) {
cx = cL[j].x;
cy = cL[j].y;
cr = cL[j].r;
x0 = pL[p0].x;
y0 = pL[p0].y;
x1 = pL[p1].x;
y1 = pL[p1].y;
a = ((x1-x0)*(cx-x0)+(y1-y0)*(cy-y0))/(sq(x1-x0)+sq(y1-y0));
a = a<0?0:a;
a = a>1?1:a;
px = pL[p0].x+(pL[p1].x-pL[p0].x)*a;
py = pL[p0].y+(pL[p1].y-pL[p0].y)*a;
d = sqrt(sq(px-cx)+sq(py-cy));
if (d < cr) {
d = 2*(cr-d);
dx = (px-cx)/cr;
dy = (py-cy)/cr;
pL[p0].x += d*dx*(1-a);
pL[p0].y += d*dy*(1-a);
pL[p1].x += d*dx*a;
pL[p1].y += d*dy*a;
}
}
if (toPoints) {
//Segment vs Point
for (int j=0; j<pL.length; j++) {
if (j == p0 || j == p1) {
continue;
}
cx = pL[j].x;
cy = pL[j].y;
cr = pL[j].r;
x0 = pL[p0].x;
y0 = pL[p0].y;
x1 = pL[p1].x;
y1 = pL[p1].y;
a = ((x1-x0)*(cx-x0)+(y1-y0)*(cy-y0))/(sq(x1-x0)+sq(y1-y0));
a = a<0?0:a;
a = a>1?1:a;
px = pL[p0].x+(pL[p1].x-pL[p0].x)*a;
py = pL[p0].y+(pL[p1].y-pL[p0].y)*a;
d = sqrt(sq(px-cx)+sq(py-cy));
if (d < cr) {
d = (cr-d);
dx = (px-cx)/cr;
dy = (py-cy)/cr;
pL[j].x -= d*dx;
pL[j].y -= d*dy;
pL[p0].x += d*dx*(1-a);
pL[p0].y += d*dy*(1-a);
pL[p1].x += d*dx*a;
pL[p1].y += d*dy*a;
}
}
}
}
}
void pointCollide(boolean toPoints) {
for (int i=0; i<pL.length; i++) {
p0r = pL[i].r;
//Point vs Circle
for (int j=0; j<cL.length; j++) {
cx = cL[j].x;
cy = cL[j].y;
cr = cL[j].r+p0r;
px = pL[i].x;
py = pL[i].y;
d = sqrt(sq(px-cx)+sq(py-cy));
if (d < cr) {
d = (cr-d);
dx = (px-cx)/cr;
dy = (py-cy)/cr;
pL[i].x += d*dx;
pL[i].y += d*dy;
}
}
if (toPoints) {
//Point vs Point
for (int j=0; j<pL.length; j++) {
if (j == i) {
continue;
}
cx = pL[j].x;
cy = pL[j].y;
cr = pL[j].r+p0r;
px = pL[i].x;
py = pL[i].y;
d = sqrt(sq(px-cx)+sq(py-cy));
if (d < cr) {
d = (cr-d);
dx = (px-cx)/cr;
dy = (py-cy)/cr;
pL[j].x -= d*dx;
pL[j].y -= d*dy;
pL[i].x += d*dx;
pL[i].y += d*dy;
}
}
}
if (pL[i].x < p0r) {
pL[i].x = p0r;
}
else if (pL[i].x > width-p0r) {
pL[i].x = width-p0r;
}
if (pL[i].y < p0r) {
pL[i].y = p0r;
}
else if (pL[i].y > height-p0r) {
pL[i].y = height-p0r;
}
}
}
void render() {
for (int i=0; i<cL.length; i++) {
ellipse(cL[i].x, cL[i].y, cL[i].r*2, cL[i].r*2);
}
for (int i=0; i<sL.length; i++) {
p0 = int(sL[i].p0);
p1 = int(sL[i].p1);
line(pL[p0].x, pL[p0].y, pL[p1].x, pL[p1].y);
}
for (int i=0; i<pL.length; i++) {
if (pL[i].r > 0) {
ellipse(pL[i].x, pL[i].y, 2*pL[i].r, 2*pL[i].r);
}
}
}
class Point {
float x, y, oX, oY, r;
Point (float Tx, float Ty, float Tr) {
x = Tx+initX;
y = Ty+initY;
oX = x;
oY = y;
r = Tr;
}
}
class Segment {
int p0, p1;
float rL;
boolean collide, fillCollide;
Segment (int Tp0, int Tp1, boolean Tcollide) {
p0 = int(Tp0);
p1 = int(Tp1);
rL = getDistance(p0, p1);
collide = Tcollide;
}
}
class Circle {
float x, y, r;
Circle (float Tx, float Ty, float Tr) {
x = Tx;
y = Ty;
r = Tr;
}
}
Last edited by Frag; 07-12-2005 at 12:33 AM.
-
cool!!
i've been meaning to look into processing for a while -- how is it?
raigan
-
Professional Air Guitarist
Hey Raigan!
It's super easy to learn. They have TONS of examples, a big and growing dictionary, and you can get nice answers to newb questions in their forums fairly quickly.
And best of all, it's FREE =D
-
Style Through Simplicity
Yea, i spent an hour looking into it and it seems really easy I seem to have a problem viewing the examples though, everything runs really really slowly. Is this just me?
Ali
-
Professional Air Guitarist
Might not change anything, but make sure you have the latest Quicktime and Java installed.
-
A very senior man
thought id post this up. just been sent a link. great ragdoll! i really need to try making one of these...
ragdoll
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|