Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
379 lines (306 sloc) 8.26 KB
extern print, currentTime;
struct Vec2d {
function void Vec2d(float x, float y) {
this->x = x;
this->y = y;
}
float x;
float y;
}
struct Point {
function void Point(float x, float y,
float mass,
int pinned) {
this->pos.x = x;
this->pos.y = y;
this->lastPos = this->pos;
this->mass = mass;
this->acc.x = 0;
this->acc.y = 0;
this->pinned = pinned;
this->debug = 0;
this->free = 0;
this->markRemove = 0;
}
Vec2d pos;
Vec2d lastPos;
Vec2d size;
float mass;
Vec2d acc;
int pinned;
int debug;
int free;
int markRemove;
}
struct Link {
function void Link(Point *p1, Point *p2,
float distRest, float stiffness, float tearness) {
this->p1 = p1;
this->p2 = p2;
this->distRest = distRest;
this->stiffness = stiffness;
this->tearness = tearness;
}
Point *p1;
Point *p2;
float distRest;
float stiffness;
float tearness;
}
let int clothW = 0;
let int clothH = 0;
let int numPoints = 0;
let Point points[500000];
//let Link* linkMap[500000][4];
let int numLinks = 0;
let Link links[500000];
let Vec2d mouse, prevMouse;
let int mouseButton = 0;
let int canvasWidth = 0;
let int mouseCut = 6;
let int mouseInfluenceSize = 30;
let int tearSensitivity = 65;
let int gravity = 0;
let int windEnabled = 0;
let int leftOverTime = 0;
let int startTime = 0;
function int min(int a, int b) {
if(a < b) {
return a;
}
return b;
}
function int bounded(int n, int low, int high) {
if(n < low) {
return low;
}
else if(n > high) {
return high;
}
return n;
}
function float distPointToLine(float x, float y, Vec2d *p1, Vec2d *p2) {
let Vec2d A;
A.x = p1->x - x;
A.y = p1->y - y;
let Vec2d B;
B.x = p2->x - p1->x;
B.y = p2->y - p1->y;
let float lenA = A.x * A.x + A.y * A.y;
let float lenB = B.x * B.x + B.y * B.y;
// It can't intersect if it's too far away
if(lenA > lenB) {
return 1000.0;
}
let float det = (-A.x * B.x) + (-A.y * A.y);
// LLJS doesn't support logical operators yet
let int bool = det < float(0.0);
if(det > lenB) {
bool = 1;
}
if(bool) {
let Vec2d C;
C.x = p2->x - x;
C.y = p2->y - y;
return min(lenA, C.x * C.x + C.y * C.y);
}
det = B.x * A.y - B.y * A.x;
return (det * det) / lenB;
}
function void update() {
let float dt = 16.0 / float(1000.0);
let int totalTime = int(currentTime()) - startTime;
for(let int z=0; z<5; z++) {
for(let int i=0; i<numLinks; i++) {
let int valid = 1;
if(links[i].p1->markRemove) {
valid = 0;
}
if(links[i].p2->markRemove) {
valid = 0;
}
if(valid) {
solveLink(&links[i]);
}
}
}
for(let int i=0; i<numPoints; i++) {
if(windEnabled) {
applyForce(&points[i],
((cos(points[i].pos.x / 30) + 1) * 200 + points[i].pos.y / 700 * 600) *
((sin(totalTime / 1000) * .5 + 1)),
0);
}
updatePoint(&points[i], dt);
}
}
function int renderLines() {
let float verts[2000000];
let int idx = 1;
for(let int i=0; i<numLinks; i++) {
let int valid = 1;
if(links[i].p1->markRemove) {
valid = 0;
}
if(links[i].p2->markRemove) {
valid = 0;
}
if(valid) {
verts[idx++] = links[i].p1->pos.x;
verts[idx++] = links[i].p1->pos.y;
verts[idx++] = links[i].p2->pos.x;
verts[idx++] = links[i].p2->pos.y;
}
}
verts[0] = idx - 1;
return int(verts);
}
// Point implementation
function void updatePoint(Point *p, float dt) {
let float dtSeq = dt * dt;
if(mouseButton) {
let Vec2d diff;
diff.x = p->pos.x - mouse.x;
diff.y = p->pos.y - mouse.y;
let float dist = sqrt(diff.x * diff.x + diff.y * diff.y);
if(mouseButton == 1) {
if(dist < float(mouseInfluenceSize)) {
p->lastPos.x = p->pos.x - bounded((mouse.x - prevMouse.x) * 1.8, -30, 30);
p->lastPos.y = p->pos.y - bounded((mouse.y - prevMouse.y) * 1.8, -30, 30);
}
}
else if(dist < float(mouseCut)) {
p->markRemove = 1;
}
}
if(!p->free) {
applyForce(p, 0, p->mass * gravity);
}
let float x = p->pos.x;
let float y = p->pos.y;
let float lx = p->lastPos.x;
let float ly = p->lastPos.y;
if(!p->pinned) {
p->lastPos = p->pos;
let Vec2d vel;
vel.x = (x - lx) * .9;
vel.y = (y - ly) * .9;
p->pos.x = x + vel.x + p->acc.x * dtSeq;
p->pos.y = y + vel.y + p->acc.y * dtSeq;
}
p->acc.x = 0;
p->acc.y = 0;
}
function void applyForce(Point *p, float x, float y) {
p->acc.x = p->acc.x + x / p->mass;
p->acc.y = p->acc.y + y / p->mass;
}
// Link implementation
function void solveLink(Link *link) {
let Point *p1 = link->p1;
let Point *p2 = link->p2;
let Vec2d diff;
diff.x = p1->pos.x - p2->pos.x;
diff.y = p1->pos.y - p2->pos.y;
let float d = sqrt(diff.x * diff.x + diff.y * diff.y);
if(d > link->tearness) {
removeLink(link);
}
let float scalar = (link->distRest - d) / d;
/* let float im1 = 1.0 / p1->mass; */
/* let float im2 = 1.0 / p2->mass; */
/* let float scalarP1 = (im1 / (im1 + im2)) * link->stiffness; */
/* let float scalarP2 = link->stiffness - scalarP1; */
if(!p1->pinned) {
p1->pos.x = p1->pos.x + diff.x * scalar * .5;
p1->pos.y = p1->pos.y + diff.y * scalar * .5;
}
if(!p2->pinned) {
p2->pos.x = p2->pos.x - diff.x * scalar * .5;
p2->pos.y = p2->pos.y - diff.y * scalar * .5;
}
}
function void removeLink(Link *link) {
link->p1->markRemove = 1;
link->p2->markRemove = 1;
}
// Init
function void constructMesh(int level) {
clothW = level + 8;
clothH = level / 2;
let int linkPtr = 0;
let int pointPtr = 0;
let float restingDistance = 700 / float(clothW - 1);
let int startX = canvasWidth / 2 - int((clothW * restingDistance) / 2);
let int startY = 0;
for(let int y=0; y<clothH; y++) {
for(let int x=0; x<clothW; x++) {
let Point p(
startX + x * restingDistance,
startY + y * restingDistance,
1, y == 0
);
let int index = y*clothW + x;
points[index] = p;
let float tearness = tearSensitivity;
if(clothH > 70) {
if(y % 2) {
if(x % 2) {
points[index].free = 1;
}
}
if(y < 10) {
tearness = 80;
}
}
if(x > 0) {
let Link l(&points[index - 1], &points[index],
restingDistance, 1, tearness);
links[linkPtr] = l;
linkPtr = linkPtr + 1;
}
if(y > 0) {
let Link l(&points[(y - 1) * clothW + x],
&points[index],
restingDistance,
1,
tearness);
links[linkPtr] = l;
linkPtr = linkPtr + 1;
}
}
}
numLinks = linkPtr;
numPoints = clothW * clothH;
}
function int getClothW() {
return clothW;
}
function int getClothH() {
return clothH;
}
function void setGravity(int value) {
gravity = value;
}
function void setWind(int flag) {
windEnabled = flag;
}
function void setMouse(int x, int y) {
mouse.x = x;
mouse.y = y;
}
function void setMouseButton(int button) {
mouseButton = button;
}
function int getMouseButton() {
return mouseButton;
}
function void mouseMove(float x, float y, int button) {
prevMouse = mouse;
mouse.x = x;
mouse.y = y;
}
function void main(int width) {
canvasWidth = width;
startTime = int(currentTime());
}