Created
December 1, 2013 07:43
-
-
Save mizchi/7729609 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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); | |
if(typeof window !== 'undefined') { | |
window.U1 = new Uint8Array(buffer); | |
window.I1 = new Int8Array(buffer); | |
window.U2 = new Uint16Array(buffer); | |
window.I2 = new Int16Array(buffer); | |
window.U4 = new Uint32Array(buffer); | |
window.I4 = new Int32Array(buffer); | |
window.F4 = new Float32Array(buffer); | |
window.F8 = new Float64Array(buffer); | |
window.asmBuffer = buffer; | |
} | |
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 print = env.print; | |
var currentTime = env.currentTime; | |
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 = 38000080; | |
var clothW = 0; | |
var clothH = 0; | |
var numPoints = 0; | |
var numLinks = 0; | |
var mouseButton = 0; | |
var canvasWidth = 0; | |
var mouseCut = 6; | |
var mouseInfluenceSize = 30; | |
var tearSensitivity = 65; | |
var gravity = 0; | |
var windEnabled = 0; | |
var leftOverTime = 0; | |
var startTime = 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, mass, pinned) { | |
thisPtr = thisPtr | 0; | |
x = +x; | |
y = +y; | |
mass = +mass; | |
pinned = pinned | 0; | |
var $SP = 0; | |
F4[((thisPtr)) >> 2] = x; | |
F4[(((thisPtr)) + 4 | 0) >> 2] = y; | |
memcpy((thisPtr) + 8 | 0 | 0, (thisPtr) | 0 | 0, 8) | 0; | |
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; | |
I4[((thisPtr) + 44 | 0) >> 2] = 0; | |
I4[((thisPtr) + 48 | 0) >> 2] = 0; | |
I4[((thisPtr) + 52 | 0) >> 2] = 0; | |
} | |
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 bounded(n, low, high) { | |
n = n | 0; | |
low = low | 0; | |
high = high | 0; | |
var $SP = 0; | |
if ((n | 0) < (low | 0)) { | |
return low | 0; | |
} else if ((n | 0) > (high | 0)) { | |
return high | 0; | |
} | |
return n | 0; | |
} | |
function distPointToLine(x, y, p1, p2) { | |
x = +x; | |
y = +y; | |
p1 = p1 | 0; | |
p2 = p2 | 0; | |
var _ = 0.0, _$1 = 0.0, _$2 = 0.0, A = 0, B = 0, lenA = 0.0, lenB = 0.0, det = 0.0, bool = 0, C = 0, $SP = 0; | |
U4[1] = (U4[1] | 0) - 24 | 0; | |
$SP = U4[1] | 0; | |
F4[(($SP)) >> 2] = +(+(+F4[(p1) >> 2]) - +x); | |
F4[((($SP)) + 4 | 0) >> 2] = +(+(+F4[((p1) + 4 | 0) >> 2]) - +y); | |
F4[(($SP) + 8 | 0) >> 2] = +(+(+F4[(p2) >> 2]) - +(+F4[(p1) >> 2])); | |
F4[((($SP) + 8 | 0) + 4 | 0) >> 2] = +(+(+F4[((p2) + 4 | 0) >> 2]) - +(+F4[((p1) + 4 | 0) >> 2])); | |
lenA = +(+(+F4[(($SP)) >> 2]) * +(+F4[(($SP)) >> 2]) + +(+F4[((($SP)) + 4 | 0) >> 2]) * +(+F4[((($SP)) + 4 | 0) >> 2])); | |
lenB = +(+(+F4[(($SP) + 8 | 0) >> 2]) * +(+F4[(($SP) + 8 | 0) >> 2]) + +(+F4[((($SP) + 8 | 0) + 4 | 0) >> 2]) * +(+F4[((($SP) + 8 | 0) + 4 | 0) >> 2])); | |
if (+lenA > +lenB) { | |
return +(_ = +1000, U4[1] = (U4[1] | 0) + 24 | 0, _); | |
} | |
det = +(+-+F4[(($SP)) >> 2] * +(+F4[(($SP) + 8 | 0) >> 2]) + +-+F4[((($SP)) + 4 | 0) >> 2] * +(+F4[((($SP)) + 4 | 0) >> 2])); | |
bool = +(+det) < +(+(+0)); | |
if (+det > +lenB) { | |
bool = 1; | |
} | |
if (bool) { | |
F4[(($SP) + 16 | 0) >> 2] = +(+(+F4[(p2) >> 2]) - +x); | |
F4[((($SP) + 16 | 0) + 4 | 0) >> 2] = +(+(+F4[((p2) + 4 | 0) >> 2]) - +y); | |
return +(_$1 = +(min(~~lenA, ~~(+(+F4[(($SP) + 16 | 0) >> 2]) * +(+F4[(($SP) + 16 | 0) >> 2]) + +(+F4[((($SP) + 16 | 0) + 4 | 0) >> 2]) * +(+F4[((($SP) + 16 | 0) + 4 | 0) >> 2]))) | 0 | 0), U4[1] = (U4[1] | 0) + 24 | 0, _$1); | |
} | |
det = +(+(+F4[(($SP) + 8 | 0) >> 2]) * +(+F4[((($SP)) + 4 | 0) >> 2]) - +(+F4[((($SP) + 8 | 0) + 4 | 0) >> 2]) * +(+F4[(($SP)) >> 2])); | |
return +(_$2 = +(+det * +det / +lenB), U4[1] = (U4[1] | 0) + 24 | 0, _$2); | |
U4[1] = (U4[1] | 0) + 24; | |
return 0.0; | |
} | |
function update() { | |
var _ = 0, _$1 = 0, _$2 = 0, dt = 0.0, totalTime = 0, z = 0, i = 0, valid = 0, i$1 = 0, $SP = 0; | |
dt = +(+16 / +(+1000)); | |
totalTime = (currentTime() | 0 | 0 | 0) - (startTime | 0 | 0) | 0 | 0; | |
for (z = 0; (z | 0) < 5; _ = z, z = (z | 0) + 1 | 0, _) { | |
for (i = 0; (i | 0) < (numLinks | 0); _$1 = i, i = (i | 0) + 1 | 0, _$1) { | |
valid = 1; | |
if (I4[((U4[((((totalSize - globalSP | 0) + 28000064 | 0) + (i * 20 | 0))) >> 2] | 0) + 52 | 0) >> 2] | 0) { | |
valid = 0; | |
} | |
if (I4[((U4[(((((totalSize - globalSP | 0) + 28000064 | 0) + (i * 20 | 0))) + 4 | 0) >> 2] | 0) + 52 | 0) >> 2] | 0) { | |
valid = 0; | |
} | |
if (valid) { | |
solveLink((((totalSize - globalSP | 0) + 28000064 | 0) + (i * 20 | 0)) | 0 | 0); | |
} | |
} | |
} | |
for (i$1 = 0; (i$1 | 0) < (numPoints | 0); _$2 = i$1, i$1 = (i$1 | 0) + 1 | 0, _$2) { | |
if (windEnabled) { | |
applyForce((((totalSize - globalSP | 0) + 64 | 0) + (i$1 * 56 | 0)) | 0 | 0, +(((+(+cos(+(+(+F4[(((((totalSize - globalSP | 0) + 64 | 0) + (i$1 * 56 | 0)))) >> 2]) / +30))) + +1) * +200 + +(+F4[((((((totalSize - globalSP | 0) + 64 | 0) + (i$1 * 56 | 0)))) + 4 | 0) >> 2]) / +700 * +600) * (+(+sin(+((totalTime | 0) / 1000 | 0 | 0))) * 0.5 + +1)), +0); | |
} | |
updatePoint((((totalSize - globalSP | 0) + 64 | 0) + (i$1 * 56 | 0)) | 0 | 0, dt); | |
} | |
} | |
function renderLines() { | |
var _ = 0, _$1 = 0, _$2 = 0, _$3 = 0, _$4 = 0, _$5 = 0, verts = 0, idx = 0, i = 0, valid = 0, $SP = 0; | |
U4[1] = (U4[1] | 0) - 8000000 | 0; | |
$SP = U4[1] | 0; | |
idx = 1; | |
for (i = 0; (i | 0) < (numLinks | 0); _ = i, i = (i | 0) + 1 | 0, _) { | |
valid = 1; | |
if (I4[((U4[((((totalSize - globalSP | 0) + 28000064 | 0) + (i * 20 | 0))) >> 2] | 0) + 52 | 0) >> 2] | 0) { | |
valid = 0; | |
} | |
if (I4[((U4[(((((totalSize - globalSP | 0) + 28000064 | 0) + (i * 20 | 0))) + 4 | 0) >> 2] | 0) + 52 | 0) >> 2] | 0) { | |
valid = 0; | |
} | |
if (valid) { | |
F4[(($SP) + ((_$1 = idx, idx = (idx | 0 | 0) + 1 | 0 | 0, _$1) * 4 | 0)) >> 2] = +F4[((U4[((((totalSize - globalSP | 0) + 28000064 | 0) + (i * 20 | 0))) >> 2] | 0)) >> 2]; | |
F4[(($SP) + ((_$2 = idx, idx = (idx | 0 | 0) + 1 | 0 | 0, _$2) * 4 | 0)) >> 2] = +F4[(((U4[((((totalSize - globalSP | 0) + 28000064 | 0) + (i * 20 | 0))) >> 2] | 0)) + 4 | 0) >> 2]; | |
F4[(($SP) + ((_$3 = idx, idx = (idx | 0 | 0) + 1 | 0 | 0, _$3) * 4 | 0)) >> 2] = +F4[((U4[(((((totalSize - globalSP | 0) + 28000064 | 0) + (i * 20 | 0))) + 4 | 0) >> 2] | 0)) >> 2]; | |
F4[(($SP) + ((_$4 = idx, idx = (idx | 0 | 0) + 1 | 0 | 0, _$4) * 4 | 0)) >> 2] = +F4[(((U4[(((((totalSize - globalSP | 0) + 28000064 | 0) + (i * 20 | 0))) + 4 | 0) >> 2] | 0)) + 4 | 0) >> 2]; | |
} | |
} | |
F4[(($SP) + (0 * 4 | 0)) >> 2] = +((idx | 0) - 1 | 0 | 0); | |
return (_$5 = ~~($SP) | 0, U4[1] = (U4[1] | 0) + 8000000 | 0, _$5) | 0; | |
U4[1] = (U4[1] | 0) + 8000000; | |
return 0; | |
} | |
function updatePoint(p, dt) { | |
p = p | 0; | |
dt = +dt; | |
var dtSeq = 0.0, diff = 0, dist = 0.0, x = 0.0, y = 0.0, lx = 0.0, ly = 0.0, vel = 0, $SP = 0; | |
U4[1] = (U4[1] | 0) - 16 | 0; | |
$SP = U4[1] | 0; | |
dtSeq = +(+dt * +dt); | |
if (mouseButton) { | |
F4[(($SP)) >> 2] = +(+(+F4[((p)) >> 2]) - +(+F4[((totalSize - globalSP | 0) + 38000064 | 0) >> 2])); | |
F4[((($SP)) + 4 | 0) >> 2] = +(+(+F4[(((p)) + 4 | 0) >> 2]) - +(+F4[(((totalSize - globalSP | 0) + 38000064 | 0) + 4 | 0) >> 2])); | |
dist = +(+sqrt(+(+(+F4[(($SP)) >> 2]) * +(+F4[(($SP)) >> 2]) + +(+F4[((($SP)) + 4 | 0) >> 2]) * +(+F4[((($SP)) + 4 | 0) >> 2])))); | |
if ((mouseButton | 0) == 1) { | |
if (+dist < +(+(mouseInfluenceSize | 0))) { | |
F4[((p) + 8 | 0) >> 2] = +(+(+F4[((p)) >> 2]) - +(bounded(~~((+(+F4[((totalSize - globalSP | 0) + 38000064 | 0) >> 2]) - +(+F4[((totalSize - globalSP | 0) + 38000072 | 0) >> 2])) * 1.8), -30, 30) | 0 | 0)); | |
F4[(((p) + 8 | 0) + 4 | 0) >> 2] = +(+(+F4[(((p)) + 4 | 0) >> 2]) - +(bounded(~~((+(+F4[(((totalSize - globalSP | 0) + 38000064 | 0) + 4 | 0) >> 2]) - +(+F4[(((totalSize - globalSP | 0) + 38000072 | 0) + 4 | 0) >> 2])) * 1.8), -30, 30) | 0 | 0)); | |
} | |
} else if (+dist < +(+(mouseCut | 0))) { | |
I4[((p) + 52 | 0) >> 2] = 1; | |
} | |
} | |
if (!(I4[((p) + 48 | 0) >> 2] | 0)) { | |
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]; | |
if (!(I4[((p) + 40 | 0) >> 2] | 0)) { | |
memcpy((p) + 8 | 0 | 0, (p) | 0 | 0, 8) | 0; | |
F4[(($SP) + 8 | 0) >> 2] = +((+x - +lx) * 0.9); | |
F4[((($SP) + 8 | 0) + 4 | 0) >> 2] = +((+y - +ly) * 0.9); | |
F4[((p)) >> 2] = +(+x + +(+F4[(($SP) + 8 | 0) >> 2]) + +(+F4[((p) + 32 | 0) >> 2]) * +dtSeq); | |
F4[(((p)) + 4 | 0) >> 2] = +(+y + +(+F4[((($SP) + 8 | 0) + 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) + 16; | |
} | |
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 solveLink(link) { | |
link = link | 0; | |
var p1 = 0, p2 = 0, diff = 0, d = 0.0, scalar = 0.0, $SP = 0; | |
U4[1] = (U4[1] | 0) - 8 | 0; | |
$SP = U4[1] | 0; | |
p1 = U4[(link) >> 2] | 0 | 0; | |
p2 = U4[((link) + 4 | 0) >> 2] | 0 | 0; | |
F4[(($SP)) >> 2] = +(+(+F4[((p1)) >> 2]) - +(+F4[((p2)) >> 2])); | |
F4[((($SP)) + 4 | 0) >> 2] = +(+(+F4[(((p1)) + 4 | 0) >> 2]) - +(+F4[(((p2)) + 4 | 0) >> 2])); | |
d = +(+sqrt(+(+(+F4[(($SP)) >> 2]) * +(+F4[(($SP)) >> 2]) + +(+F4[((($SP)) + 4 | 0) >> 2]) * +(+F4[((($SP)) + 4 | 0) >> 2])))); | |
if (+d > +(+F4[((link) + 16 | 0) >> 2])) { | |
removeLink(link | 0); | |
} | |
scalar = +((+(+F4[((link) + 8 | 0) >> 2]) - +d) / +d); | |
if (!(I4[((p1) + 40 | 0) >> 2] | 0)) { | |
F4[((p1)) >> 2] = +(+(+F4[((p1)) >> 2]) + +(+F4[(($SP)) >> 2]) * +scalar * 0.5); | |
F4[(((p1)) + 4 | 0) >> 2] = +(+(+F4[(((p1)) + 4 | 0) >> 2]) + +(+F4[((($SP)) + 4 | 0) >> 2]) * +scalar * 0.5); | |
} | |
if (!(I4[((p2) + 40 | 0) >> 2] | 0)) { | |
F4[((p2)) >> 2] = +(+(+F4[((p2)) >> 2]) - +(+F4[(($SP)) >> 2]) * +scalar * 0.5); | |
F4[(((p2)) + 4 | 0) >> 2] = +(+(+F4[(((p2)) + 4 | 0) >> 2]) - +(+F4[((($SP)) + 4 | 0) >> 2]) * +scalar * 0.5); | |
} | |
U4[1] = (U4[1] | 0) + 8; | |
} | |
function removeLink(link) { | |
link = link | 0; | |
var $SP = 0; | |
I4[((U4[(link) >> 2] | 0) + 52 | 0) >> 2] = 1; | |
I4[((U4[((link) + 4 | 0) >> 2] | 0) + 52 | 0) >> 2] = 1; | |
} | |
function constructMesh(level) { | |
level = level | 0; | |
var _ = 0, _$1 = 0, linkPtr = 0, pointPtr = 0, restingDistance = 0.0, startX = 0, startY = 0, y = 0, x = 0, p = 0, index = 0, tearness = 0.0, l = 0, l$1 = 0, $SP = 0; | |
U4[1] = (U4[1] | 0) - 104 | 0; | |
$SP = U4[1] | 0; | |
clothW = (level | 0) + 8 | 0; | |
clothH = (level | 0) / 2 | 0; | |
linkPtr = 0; | |
pointPtr = 0; | |
restingDistance = +(+700 / +(+((clothW | 0 | 0) - 1 | 0 | 0 | 0))); | |
startX = ((canvasWidth | 0 | 0) / 2 | 0 | 0 | 0 | 0) - (~~(+(clothW | 0) * +restingDistance / +2) | 0 | 0) | 0 | 0; | |
startY = 0; | |
for (y = 0; (y | 0) < (clothH | 0); _ = y, y = (y | 0) + 1 | 0, _) { | |
for (x = 0; (x | 0) < (clothW | 0); _$1 = x, x = (x | 0) + 1 | 0, _$1) { | |
(Point$Point(($SP) | 0 | 0 | 0, +(+(startX | 0) + +(x | 0) * +restingDistance), +(+(startY | 0) + +(y | 0) * +restingDistance), +1, (y | 0 | 0) == 0), F4[($SP) >> 2]); | |
index = (imul(y | 0, clothW | 0) | 0 | 0 | 0) + (x | 0 | 0) | 0 | 0; | |
memcpy((((totalSize - globalSP | 0) + 64 | 0) + (index * 56 | 0)) | 0 | 0, ($SP) | 0 | 0, 56) | 0; | |
tearness = +(tearSensitivity | 0); | |
if ((clothH | 0) > 70) { | |
if ((y | 0) % 2 | 0) { | |
if ((x | 0) % 2 | 0) { | |
I4[(((((totalSize - globalSP | 0) + 64 | 0) + (index * 56 | 0))) + 48 | 0) >> 2] = 1; | |
} | |
} | |
if ((y | 0) < 10) { | |
tearness = +80; | |
} | |
} | |
if ((x | 0) > 0) { | |
(Link$Link(($SP) + 56 | 0 | 0 | 0, (((totalSize - globalSP | 0) + 64 | 0) + (((index | 0 | 0 | 0) - 1 | 0 | 0 | 0) * 56 | 0)) | 0 | 0 | 0, (((totalSize - globalSP | 0) + 64 | 0) + (index * 56 | 0)) | 0 | 0 | 0, restingDistance, +1, tearness), U4[(($SP) + 56 | 0) >> 2]); | |
memcpy((((totalSize - globalSP | 0) + 28000064 | 0) + (linkPtr * 20 | 0)) | 0 | 0, ($SP) + 56 | 0 | 0, 20) | 0; | |
linkPtr = (linkPtr | 0) + 1 | 0; | |
} | |
if ((y | 0) > 0) { | |
(Link$Link(($SP) + 80 | 0 | 0 | 0, (((totalSize - globalSP | 0) + 64 | 0) + (((imul((y | 0 | 0 | 0) - 1 | 0 | 0 | 0, clothW | 0) | 0 | 0 | 0 | 0) + (x | 0 | 0 | 0) | 0 | 0 | 0) * 56 | 0)) | 0 | 0 | 0, (((totalSize - globalSP | 0) + 64 | 0) + (index * 56 | 0)) | 0 | 0 | 0, restingDistance, +1, tearness), U4[(($SP) + 80 | 0) >> 2]); | |
memcpy((((totalSize - globalSP | 0) + 28000064 | 0) + (linkPtr * 20 | 0)) | 0 | 0, ($SP) + 80 | 0 | 0, 20) | 0; | |
linkPtr = (linkPtr | 0) + 1 | 0; | |
} | |
} | |
} | |
numLinks = linkPtr; | |
numPoints = imul(clothW, clothH) | 0; | |
U4[1] = (U4[1] | 0) + 104; | |
} | |
function getClothW() { | |
var $SP = 0; | |
return clothW | 0; | |
} | |
function getClothH() { | |
var $SP = 0; | |
return clothH | 0; | |
} | |
function setGravity(value) { | |
value = value | 0; | |
var $SP = 0; | |
gravity = value; | |
} | |
function setWind(flag) { | |
flag = flag | 0; | |
var $SP = 0; | |
windEnabled = flag; | |
} | |
function setMouse(x, y) { | |
x = x | 0; | |
y = y | 0; | |
var $SP = 0; | |
F4[((totalSize - globalSP | 0) + 38000064 | 0) >> 2] = +(x | 0); | |
F4[(((totalSize - globalSP | 0) + 38000064 | 0) + 4 | 0) >> 2] = +(y | 0); | |
} | |
function setMouseButton(button) { | |
button = button | 0; | |
var $SP = 0; | |
mouseButton = button; | |
} | |
function getMouseButton() { | |
var $SP = 0; | |
return mouseButton | 0; | |
} | |
function mouseMove(x, y, button) { | |
x = +x; | |
y = +y; | |
button = button | 0; | |
var $SP = 0; | |
memcpy((totalSize - globalSP | 0) + 38000072 | 0 | 0, (totalSize - globalSP | 0) + 38000064 | 0 | 0, 8) | 0; | |
F4[((totalSize - globalSP | 0) + 38000064 | 0) >> 2] = x; | |
F4[(((totalSize - globalSP | 0) + 38000064 | 0) + 4 | 0) >> 2] = y; | |
} | |
function main(width) { | |
width = width | 0; | |
var $SP = 0; | |
U4[1] = totalSize - 38000080; | |
U4[0] = 4; | |
canvasWidth = width; | |
startTime = currentTime() | 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 { main: main }; | |
})({ Uint8Array: Uint8Array, | |
Int8Array: Int8Array, | |
Uint16Array: Uint16Array, | |
Int16Array: Int16Array, | |
Uint32Array: Uint32Array, | |
Int32Array: Int32Array, | |
Float32Array: Float32Array, | |
Float64Array: Float64Array, | |
Math: Math }, | |
{ print: print, | |
currentTime: currentTime, | |
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; | |
} | |
asm.main(); | |
})(); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment