Skip to content

Instantly share code, notes, and snippets.

@jlongster
Last active December 16, 2015 03:29
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jlongster/5369811 to your computer and use it in GitHub Desktop.
Save jlongster/5369811 to your computer and use it in GitHub Desktop.
large LLJS example
extern clear, fillRect, renderLine, print;
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 sizeX, float sizeY,
float mass,
int pinned) {
this->pos.x = x;
this->pos.y = y;
this->lastPos = this->pos;
this->size.x = sizeX;
this->size.y = sizeY;
this->mass = mass;
this->acc.x = 0;
this->acc.y = 0;
this->pinned = pinned;
}
Vec2d pos;
Vec2d lastPos;
Vec2d size;
float mass;
Vec2d acc;
int pinned;
}
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 = 10;
let int clothH = 10;
let int numPoints = 100;
let int numLinks = 2;
let Point points[100];
let int gravity = 500;
let int leftOverTime = 0;
function int min(int a, int b) {
if(a < b) {
return a;
}
return b;
}
function void update(int dt) {
let int steps = min((dt + leftOverTime) / 16, 5);
leftOverTime = dt - steps * 16;
for(let int i = 0; i<steps; i = i + 1) {
updateStep(float(16.0) / float(1000.0));
}
}
function void updateStep(float dt) {
for(let int z=0; z<3; z = z + 1) {
for(let int i=0; i<numPoints; i = i + 1) {
solveConstraints(&points[i]);
}
}
for(let int i=0; i<numPoints; i = i + 1) {
updatePoint(&points[i], dt);
}
}
function void render() {
clear();
for(let int j=0; j<numPoints; j = j + 1) {
fillRect(points[j].pos.x,
points[j].pos.y,
points[j].size.x,
points[j].size.y);
}
}
function void solveConstraints(Point *p) {
}
function void updatePoint(Point *p, float dt) {
let float dtSeq = dt * dt;
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;
p->lastPos = p->pos;
let Vec2d vel((x - lx) * .99, (y - ly) * .99);
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;
}
function void main(int width) {
let float restingDistance = 6;
let int minWidth = width / 2 - int((clothW * restingDistance) / 2);
let int minHeight = 25;
for(let int y=0; y<clothH; y = y + 1) {
for(let int x=0; x<clothW; x = x + 1) {
let Point p(
minWidth + x * restingDistance,
minHeight + y * restingDistance,
3, 3,
1, y == 0
);
points[y*clothW + x] = p;
}
}
}
(function() {
if(!Math.imul) {
Math.imul = function(x, y) { return x * y; };
}
var MB = 1024 * 1024;
var SIZE = 256 * MB;
var STACK_SIZE = 2 * MB;
var HEAP_SIZE = SIZE - STACK_SIZE;
var buffer = new ArrayBuffer(SIZE);
var asm = (function (global, env, buffer) {
"use asm";
var stackSize = env.STACK_SIZE|0;
var heapSize = env.HEAP_SIZE|0;
var totalSize = env.TOTAL_SIZE|0;
var clear = env.clear;
var fillRect = env.fillRect;
var renderLine = env.renderLine;
var print = env.print;
var U1 = new global.Uint8Array(buffer);
var I1 = new global.Int8Array(buffer);
var U2 = new global.Uint16Array(buffer);
var I2 = new global.Int16Array(buffer);
var U4 = new global.Uint32Array(buffer);
var I4 = new global.Int32Array(buffer);
var F4 = new global.Float32Array(buffer);
var F8 = new global.Float64Array(buffer);
var acos = global.Math.acos;
var asin = global.Math.asin;
var atan = global.Math.atan;
var cos = global.Math.cos;
var sin = global.Math.sin;
var tan = global.Math.tan;
var ceil = global.Math.ceil;
var floor = global.Math.floor;
var exp = global.Math.exp;
var log = global.Math.log;
var sqrt = global.Math.sqrt;
var abs = global.Math.abs;
var atan2 = global.Math.atan2;
var pow = global.Math.pow;
var imul = global.Math.imul;
var globalSP = 4464;
var clothW = 10;
var clothH = 10;
var numPoints = 100;
var numLinks = 2;
var gravity = 500;
var leftOverTime = 0;
function Vec2d$Vec2d(thisPtr, x, y) {
thisPtr = thisPtr | 0;
x = +x;
y = +y;
var $SP = 0;
F4[(thisPtr) >> 2] = x;
F4[((thisPtr) + 4 | 0) >> 2] = y;
}
function Point$Point(thisPtr, x, y, sizeX, sizeY, mass, pinned) {
thisPtr = thisPtr | 0;
x = +x;
y = +y;
sizeX = +sizeX;
sizeY = +sizeY;
mass = +mass;
pinned = pinned | 0;
var $SP = 0;
F4[((thisPtr)) >> 2] = x;
F4[(((thisPtr)) + 4 | 0) >> 2] = y;
memcpy((thisPtr) + 8 | 0, (thisPtr) | 0, 8);
F4[((thisPtr) + 16 | 0) >> 2] = sizeX;
F4[(((thisPtr) + 16 | 0) + 4 | 0) >> 2] = sizeY;
F4[((thisPtr) + 24 | 0) >> 2] = mass;
F4[((thisPtr) + 32 | 0) >> 2] = +0;
F4[(((thisPtr) + 32 | 0) + 4 | 0) >> 2] = +0;
I4[((thisPtr) + 40 | 0) >> 2] = pinned;
}
function Link$Link(thisPtr, p1, p2, distRest, stiffness, tearness) {
thisPtr = thisPtr | 0;
p1 = p1 | 0;
p2 = p2 | 0;
distRest = +distRest;
stiffness = +stiffness;
tearness = +tearness;
var $SP = 0;
U4[(thisPtr) >> 2] = p1 | 0;
U4[((thisPtr) + 4 | 0) >> 2] = p2 | 0;
F4[((thisPtr) + 8 | 0) >> 2] = distRest;
F4[((thisPtr) + 12 | 0) >> 2] = stiffness;
F4[((thisPtr) + 16 | 0) >> 2] = tearness;
}
function min(a, b) {
a = a | 0;
b = b | 0;
var $SP = 0;
if ((a | 0) < (b | 0)) {
return a | 0;
}
return b | 0;
}
function update(dt) {
dt = dt | 0;
var steps = 0, i = 0, $SP = 0;
steps = min(((dt | 0 | 0) + (leftOverTime | 0 | 0) | 0 | 0 | 0 | 0) / 16 | 0 | 0, 5);
leftOverTime = (dt | 0) - (imul(steps, 16) | 0) | 0;
for (i = 0; (i | 0) < (steps | 0); i = (i | 0) + 1 | 0) {
updateStep(+(+(+16) / +(+1000)));
}
}
function updateStep(dt) {
dt = +dt;
var z = 0, i = 0, i$1 = 0, $SP = 0;
for (z = 0; (z | 0) < 3; z = (z | 0) + 1 | 0) {
for (i = 0; (i | 0) < (numPoints | 0); i = (i | 0) + 1 | 0) {
solveConstraints((((totalSize - globalSP | 0) + 64 | 0) + i * 44) | 0);
}
}
for (i$1 = 0; (i$1 | 0) < (numPoints | 0); i$1 = (i$1 | 0) + 1 | 0) {
updatePoint((((totalSize - globalSP | 0) + 64 | 0) + i$1 * 44) | 0, dt);
}
}
function render() {
var j = 0, $SP = 0;
clear();
for (j = 0; (j | 0) < (numPoints | 0); j = (j | 0) + 1 | 0) {
fillRect(+F4[(((((totalSize - globalSP | 0) + 64 | 0) + j * 44))) >> 2], +F4[((((((totalSize - globalSP | 0) + 64 | 0) + j * 44))) + 4 | 0) >> 2], +F4[(((((totalSize - globalSP | 0) + 64 | 0) + j * 44)) + 16 | 0) >> 2], +F4[((((((totalSize - globalSP | 0) + 64 | 0) + j * 44)) + 16 | 0) + 4 | 0) >> 2]);
}
}
function solveConstraints(p) {
p = p | 0;
var $SP = 0;
}
function updatePoint(p, dt) {
p = p | 0;
dt = +dt;
var dtSeq = 0.0, x = 0.0, y = 0.0, lx = 0.0, ly = 0.0, vel = 0, $SP = 0;
U4[1] = (U4[1] | 0) - 8;
$SP = U4[1] | 0;
dtSeq = +(+dt * +dt);
applyForce(p | 0, +0, +(+(+F4[((p) + 24 | 0) >> 2]) * +(gravity | 0)));
x = +F4[((p)) >> 2];
y = +F4[(((p)) + 4 | 0) >> 2];
lx = +F4[((p) + 8 | 0) >> 2];
ly = +F4[(((p) + 8 | 0) + 4 | 0) >> 2];
memcpy((p) + 8 | 0, (p) | 0, 8);
(Vec2d$Vec2d(($SP) | 0 | 0, +((+x - +lx) * 0.99), +((+y - +ly) * 0.99)), F4[($SP) >> 2]);
F4[((p)) >> 2] = +(+x + +(+F4[(($SP)) >> 2]) + +(+F4[((p) + 32 | 0) >> 2]) * +dtSeq);
F4[(((p)) + 4 | 0) >> 2] = +(+y + +(+F4[((($SP)) + 4 | 0) >> 2]) + +(+F4[(((p) + 32 | 0) + 4 | 0) >> 2]) * +dtSeq);
F4[((p) + 32 | 0) >> 2] = +0;
F4[(((p) + 32 | 0) + 4 | 0) >> 2] = +0;
U4[1] = (U4[1] | 0) + 8;
return 0.0;
}
function applyForce(p, x, y) {
p = p | 0;
x = +x;
y = +y;
var $SP = 0;
F4[((p) + 32 | 0) >> 2] = +(+(+F4[((p) + 32 | 0) >> 2]) + +x / +(+F4[((p) + 24 | 0) >> 2]));
F4[(((p) + 32 | 0) + 4 | 0) >> 2] = +(+(+F4[(((p) + 32 | 0) + 4 | 0) >> 2]) + +y / +(+F4[((p) + 24 | 0) >> 2]));
}
function main(width) {
width = width | 0;
var restingDistance = 0.0, minWidth = 0, minHeight = 0, y = 0, x = 0, p = 0, $SP = 0;
U4[1] = totalSize - 4464;
U4[0] = 4;
U4[1] = (U4[1] | 0) - 48;
$SP = U4[1] | 0;
restingDistance = +6.0;
minWidth = ((width | 0 | 0) / 2 | 0 | 0 | 0 | 0) - (~~(+(clothW | 0) * +restingDistance / +2) | 0 | 0) | 0 | 0;
minHeight = 25;
for (y = 0; (y | 0) < (clothH | 0); y = (y | 0) + 1 | 0) {
for (x = 0; (x | 0) < (clothW | 0); x = (x | 0) + 1 | 0) {
(Point$Point(($SP) | 0 | 0, +(+(minWidth | 0) + +(x | 0) * +restingDistance), +(+(minHeight | 0) + +(y | 0) * +restingDistance), +3, +3, +1, (y | 0 | 0) == 0), F4[($SP) >> 2]);
memcpy((((totalSize - globalSP | 0) + 64 | 0) + ((imul(y | 0, clothW | 0) | 0 | 0 | 0) + (x | 0 | 0 | 0) | 0 | 0 | 0) * 44) | 0, ($SP) | 0, 44);
}
}
U4[1] = (U4[1] | 0) + 48;
return 0.0;
}
function memcpy(dest, src, num) {
dest = dest|0; src = src|0; num = num|0;
var ret = 0;
ret = dest|0;
if ((dest&3) == (src&3)) {
while (dest & 3) {
if ((num|0) == 0) return ret|0;
U1[(dest)]=U1[(src)];
dest = (dest+1)|0;
src = (src+1)|0;
num = (num-1)|0;
}
while ((num|0) >= 4) {
U4[((dest)>>2)]=U4[((src)>>2)];
dest = (dest+4)|0;
src = (src+4)|0;
num = (num-4)|0;
}
}
while ((num|0) > 0) {
U1[(dest)]=U1[(src)];
dest = (dest+1)|0;
src = (src+1)|0;
num = (num-1)|0;
}
return ret|0;
}
function memset(ptr, value, num) {
ptr = ptr|0; value = value|0; num = num|0;
var stop = 0, value4 = 0, stop4 = 0, unaligned = 0;
stop = (ptr + num)|0;
if ((num|0) >= 20) {
// This is unaligned, but quite large, so work hard to get to aligned settings
value = value & 0xff;
unaligned = ptr & 3;
value4 = value | (value << 8) | (value << 16) | (value << 24);
stop4 = stop & ~3;
if (unaligned) {
unaligned = (ptr + 4 - unaligned)|0;
while ((ptr|0) < (unaligned|0)) { // no need to check for stop, since we have large num
U1[(ptr)]=value;
ptr = (ptr+1)|0;
}
}
while ((ptr|0) < (stop4|0)) {
U4[((ptr)>>2)]=value4;
ptr = (ptr+4)|0;
}
}
while ((ptr|0) < (stop|0)) {
U1[(ptr)]=value;
ptr = (ptr+1)|0;
}
}
return { update: update,
render: render,
main: main };
})({ Uint8Array: Uint8Array,
Int8Array: Int8Array,
Uint16Array: Uint16Array,
Int16Array: Int16Array,
Uint32Array: Uint32Array,
Int32Array: Int32Array,
Float32Array: Float32Array,
Float64Array: Float64Array,
Math: Math },
{ clear: clear,
fillRect: fillRect,
renderLine: renderLine,
print: print,
HEAP_SIZE: HEAP_SIZE,
STACK_SIZE: STACK_SIZE,
TOTAL_SIZE: SIZE },
buffer);
function assertEqual(val1, val2) {
var err = true;
var msg;
if(val1 | 0 !== val1) {
if(Math.abs(val1 - val2) < .00000001) {
err = false;
}
else {
msg = 'eps';
}
}
else if(val1 === val2) {
err = false;
}
if(err) {
throw new Error(val1 + ' does not equal ' + val2);
}
}
function _print(/* arg1, arg2, ..., argN */) {
var func = ((typeof console !== 'undefined' && console.log) || print);
func.apply(null, arguments);
}
var _time;
function start() {
_time = Date.now();
}
function end() {
return Date.now() - _time;
}
window.verlet = asm;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment