From e965ed809e91079496f5b2d711ceb3e5e7b99f3d Mon Sep 17 00:00:00 2001 From: mattkae Date: Sun, 6 Feb 2022 16:36:56 -0500 Subject: Working softbody simulation --- 2d/softbody/softbody_1/dist/output.wasm | Bin 58758 -> 58771 bytes 2d/softbody/softbody_2/SpringRectangle.h | 244 ++++++++++++++----------------- 2d/softbody/softbody_2/dist/output.js | 118 ++++++--------- 2d/softbody/softbody_2/dist/output.wasm | Bin 43836 -> 45315 bytes 4 files changed, 153 insertions(+), 209 deletions(-) (limited to '2d') diff --git a/2d/softbody/softbody_1/dist/output.wasm b/2d/softbody/softbody_1/dist/output.wasm index 8f7c621..a66202f 100755 Binary files a/2d/softbody/softbody_1/dist/output.wasm and b/2d/softbody/softbody_1/dist/output.wasm differ diff --git a/2d/softbody/softbody_2/SpringRectangle.h b/2d/softbody/softbody_2/SpringRectangle.h index e2cdf60..2965efa 100644 --- a/2d/softbody/softbody_2/SpringRectangle.h +++ b/2d/softbody/softbody_2/SpringRectangle.h @@ -7,51 +7,47 @@ struct PointMassUpdateData { Vector2 restingPosition; // Position is in world coordinates Vector2 currentPosition; // Position is in world coordinates Vector2 velocity; + Vector2 acceleration; Vector2 force; bool isHovered = false; PointMassUpdateData* neighbors[4]; }; -EM_BOOL onMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); -EM_BOOL onMouseDown(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); -EM_BOOL onMouseUp(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); - struct SoftbodyRectangle { // User defined float32 width = 200; float32 height = 200; - int32 springDensity = 10; - float32 k = 3.f; // in N /m - float32 c = 3.f; - float32 jointMassKg = 1.f; + int32 springDensity = 16; + float32 k = 10000000.f; // in N /m + float32 c = 9000.f; + float32 jointMassKg = 10.f; + float32 floorPosition = 0; // Calculated before runtime Vector2 springDimensions; // Runtime data - float32 totalTimeSeconds = 0.f; PointMassUpdateData* updateData = NULL; - bool hasLastPositionChanged = false; - Vector2 lastMousePosition; - PointMassUpdateData* draggedVertex = NULL; // Render data Mesh2d mesh; Mesh2d pointsMesh; + Mesh2d floorMesh; Vertex2d* vertices = NULL; Vertex2d* pointsVertices = NULL; void load(Renderer2d* renderer) { - Vector2 position = Vector2(800 / 2 - width / 2, 600 / 2 - height / 2); + auto defaultPosition = Vector2(800 / 2 - width / 2, 400); springDimensions = Vector2(width / springDensity, height / springDensity); int32 numVertices = springDensity * springDensity; // Each subdivision is a square. int32 numIndices = 6 * ((springDensity - 1) * (springDensity - 1)); vertices = new Vertex2d[numVertices]; updateData = new PointMassUpdateData[numVertices]; + pointsVertices = new Vertex2d[numVertices]; auto indices = new GLuint[numIndices]; - // Load a square with the desired density + // -- Load a square with the desired density int32 vIdx = 0; int32 iIdx = 0; float32 inverseDensity = 1.f / springDensity; @@ -59,24 +55,26 @@ struct SoftbodyRectangle { for (int32 y = 0; y < springDensity; y++) { // Rows for (int32 x = 0; x < springDensity; x++) { // Columns Vector2 vpos = Vector2(x * inverseDensity - halfInv, y * inverseDensity- halfInv); - vpos.x = vpos.x * width + position.x; - vpos.y = vpos.y * height + position.y; + vpos.x = vpos.x * width + defaultPosition.x; + vpos.y = vpos.y * height + defaultPosition.y; vertices[vIdx] = { vpos, Vector4(1, 0, 0, 1) }; updateData[vIdx].index = vIdx; - updateData[vIdx].restingPosition = vpos; + updateData[vIdx].restingPosition = vpos; updateData[vIdx].currentPosition = vpos; updateData[vIdx].force = Vector2(0, 0); updateData[vIdx].velocity = Vector2(0, 0); + updateData[vIdx].acceleration = Vector2(0, 0); - if (x != 0) updateData[vIdx].neighbors[0] = &updateData[vIdx - 1]; // Left + if (x != springDensity - 1) updateData[vIdx].neighbors[0] = &updateData[vIdx + 1]; // Right else updateData[vIdx].neighbors[0] = NULL; - if (x != springDensity - 1) updateData[vIdx].neighbors[1] = &updateData[vIdx + 1]; // Right + if (y != springDensity - 1) updateData[vIdx].neighbors[1] = &updateData[vIdx + springDensity]; // Bottom else updateData[vIdx].neighbors[1] = NULL; - if (y != 0) updateData[vIdx].neighbors[2] = &updateData[vIdx - springDensity]; // Top + if (x != 0) updateData[vIdx].neighbors[2] = &updateData[vIdx - 1]; // Left else updateData[vIdx].neighbors[2] = NULL; - if (y != springDensity - 1) updateData[vIdx].neighbors[3] = &updateData[vIdx + springDensity]; // Bottom + if (y != 0) updateData[vIdx].neighbors[3] = &updateData[vIdx - springDensity]; // Top else updateData[vIdx].neighbors[3] = NULL; + if (y != springDensity - 1 && x != springDensity - 1) { indices[iIdx++] = vIdx; @@ -87,132 +85,129 @@ struct SoftbodyRectangle { indices[iIdx++] = vIdx + 1; } + pointsVertices[vIdx].position = vpos; + pointsVertices[vIdx].color = Vector4(0, 0, 0, 1); + vIdx++; } } mesh.load(vertices, numVertices, indices, numIndices, renderer, GL_DYNAMIC_DRAW); - - pointsVertices = new Vertex2d[numVertices]; - for (int32 v = 0; v < numVertices; v++) { - pointsVertices[v].position = vertices[v].position; - pointsVertices[v].color = Vector4(0, 0, 0, 1); - } pointsMesh.load(pointsVertices, numVertices, renderer, GL_DYNAMIC_DRAW); - delete [] indices; - // Setup callbacks - emscripten_set_mousemove_callback("#gl_canvas", this, false, onMouseMove); - emscripten_set_mousedown_callback("#gl_canvas", this, false, onMouseDown); - emscripten_set_mouseup_callback("#gl_canvas", this, false, onMouseUp); + // -- Load the floor line; + Vector2 floorDimensions = Vector2(renderer->context->width, 8); + floorPosition = 100.f; + Vector4 floorColor = Vector4(0.5, 0.5, 0.5, 1); + Vertex2d floorVertices[6]; + floorVertices[0] = { Vector4(0, floorPosition, 0, 1), floorColor }; + floorVertices[1] = { Vector4(floorDimensions.x, floorPosition, 0, 1), floorColor }; + floorVertices[2] = { Vector4(0, floorPosition - floorDimensions.y, 0, 1), floorColor }; + floorVertices[3] = { Vector4(0, floorPosition - floorDimensions.y, 0, 1), floorColor }; + floorVertices[4] = { Vector4(floorDimensions.x, floorPosition - floorDimensions.y, 0, 1), floorColor }; + floorVertices[5] = { Vector4(floorDimensions.x, floorPosition, 0, 1), floorColor }; + floorMesh.load(floorVertices, 6, renderer); } Vector2 getForceBetweenPointMasses(PointMassUpdateData* first, PointMassUpdateData* second) { auto relativeVelocity = second->velocity - first->velocity; - auto restLength = (first->restingPosition - second->restingPosition).length(); + auto restLength = (second->restingPosition - first->restingPosition).length(); auto relativePosition = second->currentPosition - first->currentPosition; auto currentLength = relativePosition.length(); auto positionDir = relativePosition.normalize(); - auto dotProduct = positionDir.dot(relativeVelocity); + auto velDotProduct = positionDir.dot(relativeVelocity); + auto accelDotProduct = positionDir.dot(second->acceleration - first->acceleration); float32 springForce = k * (currentLength - restLength); - float32 dampingForce = c * dotProduct; - float32 totalForce = springForce + dampingForce; - + float32 dampingForce = c * velDotProduct; + float32 accelerationForce = jointMassKg * accelDotProduct; + float32 totalForce = accelerationForce + springForce + dampingForce; + return positionDir * totalForce; } void update(float32 dtSeconds) { - totalTimeSeconds += dtSeconds; - - for (int32 v = 0; v < pointsMesh.numVertices; v++) { + for (int32 v = 0; v < pointsMesh.numVertices; v++) { auto pointMass = &updateData[v]; - if (draggedVertex != NULL) { - if (pointMass == draggedVertex && hasLastPositionChanged) { - hasLastPositionChanged = false; - Vector2 displacement = lastMousePosition - pointMass->restingPosition; - - // We need to limit the new position based off of the triangle - if (displacement.x > springDimensions.x) { - displacement.x = springDimensions.x; - } - else if (displacement.x < -springDimensions.x) { - displacement.x = -springDimensions.x; - } - - if (displacement.y > springDimensions.y) { - displacement.y = springDimensions.y; - } - else if (displacement.y < -springDimensions.y) { - displacement.y = -springDimensions.y; - } - - pointMass->currentPosition = pointMass->restingPosition + displacement; - vertices[v].position = pointMass->currentPosition; - pointsVertices[v].position = pointMass->currentPosition; - } - } - else { - // Add the forces from it's neighbors - for (int32 n = 0; n < 4; n++) { - auto neighbor = pointMass->neighbors[n]; - if (neighbor == NULL) continue; + // -- Add the forces from it's neighbors. Note that we only do the first two + // neighbors, which are the right and bottom neighbors. + for (int32 n = 0; n < 2; n++) { + auto neighbor = pointMass->neighbors[n]; + if (neighbor == NULL) continue; - pointMass->force += getForceBetweenPointMasses(pointMass, neighbor); - } - - pointMass->velocity = pointMass->velocity + (pointMass->force / jointMassKg) * dtSeconds; - pointMass->currentPosition = pointMass->currentPosition + (pointMass->velocity * dtSeconds); - - const float32 COLLISION_DISTANCE = 4.f; - for (int32 n = 0; n < pointsMesh.numVertices; n++) { - if (n == v) continue; - auto neighbor = &updateData[n]; - - if ((neighbor->currentPosition - pointMass->currentPosition).length() < COLLISION_DISTANCE) { - auto positionNormal = (neighbor->currentPosition - pointMass->currentPosition).normalize(); - pointMass->currentPosition = neighbor->currentPosition - positionNormal * COLLISION_DISTANCE; - float32 dotProduct = pointMass->velocity.dot(positionNormal); - pointMass->velocity = pointMass->velocity - positionNormal * (2 * dotProduct); - } - } + auto forceBetween = getForceBetweenPointMasses(pointMass, neighbor); + pointMass->force = pointMass->force + forceBetween; + neighbor->force = neighbor->force- forceBetween; + } + } - vertices[v].position = pointMass->currentPosition; - pointsVertices[v].position = pointMass->currentPosition; - - // Hovering highlights behavior - if (hasLastPositionChanged) { - if ((pointMass->currentPosition - lastMousePosition).length() < 10.f) { - pointsVertices[v].color = Vector4(1, 1, 0, 1); - pointMass->isHovered = true; - - for (int32 n = 0; n < 4; n++) { - if (pointMass->neighbors[n]) - pointsVertices[pointMass->neighbors[n]->index].color = Vector4(0, 0, 1, 1); - } - } - else if (pointMass->isHovered) { - pointsVertices[v].color = Vector4(0, 0, 0, 1); - for (int32 n = 0; n < 4; n++) { - if (pointMass->neighbors[n] && !pointMass->neighbors[n]->isHovered) - pointsVertices[pointMass->neighbors[n]->index].color = Vector4(0, 0, 0, 1); - } - pointMass->isHovered = false; - } + // -- Update the local position of each vertex. + for (int32 v = 0; v < pointsMesh.numVertices; v++) { + auto pointMass = &updateData[v]; + auto prevPos = pointMass->currentPosition; + + // -- Gravity + Vector2 g = Vector2(0, -9.8 * jointMassKg) * dtSeconds; + + // -- Euler integration to find the current velocity and position + pointMass->acceleration = (pointMass->force / jointMassKg) * dtSeconds; + pointMass->velocity = pointMass->velocity + pointMass->acceleration * dtSeconds + g; + pointMass->restingPosition = pointMass->restingPosition + g * dtSeconds; + pointMass->currentPosition = pointMass->currentPosition + (pointMass->velocity * dtSeconds); + + pointMass->force = Vector2(0, 0); // Reset the force for the next update + + particleFloorCollision(pointMass, prevPos, dtSeconds); + + // -- Collision detection + const float32 COLLISION_DISTANCE = 0.3f; + for (int32 n = 0; n < 4; n++) { + auto neighbor = pointMass->neighbors[n]; + if (neighbor == NULL) continue; + + if ((neighbor->currentPosition - pointMass->currentPosition).length() < COLLISION_DISTANCE) { + auto positionNormal = (neighbor->currentPosition - pointMass->currentPosition).normalize(); + pointMass->currentPosition = neighbor->currentPosition - positionNormal * COLLISION_DISTANCE; + float32 dotProduct = pointMass->velocity.dot(positionNormal); + pointMass->velocity = pointMass->velocity - positionNormal * (2 * dotProduct); } } + + vertices[v].position = pointMass->currentPosition; + pointsVertices[v].position = pointMass->currentPosition; } - if (hasLastPositionChanged) hasLastPositionChanged = false; + // -- Update vertices mesh.updateVertices(vertices); pointsMesh.updateVertices(pointsVertices); } + void particleFloorCollision(PointMassUpdateData* ud, Vector2 prevPos, float32 dtSeconds) { + // We assume that the floor is always horizontal for this simulation + auto dotProduct = ud->velocity.dot(Vector2(0, 1)); + if (dotProduct >= 0) { + return; // Not moving in the same direction + } + + if (ud->currentPosition.y - floorPosition < 0.1f) { + // Find the point in the simulation at which we began intersecting, and then reflect. + Vector2 newPosition; + do { + dtSeconds = dtSeconds - 0.02f; + newPosition = prevPos + ud->velocity * dtSeconds; + } while (newPosition.y < floorPosition); + + ud->currentPosition = newPosition; + ud->velocity = (ud->velocity - Vector2(0, 1) * (2 * dotProduct)) * 0.5f; + } + } + void render(Renderer2d* renderer) { mesh.render(renderer); pointsMesh.render(renderer, GL_POINTS); + floorMesh.render(renderer); } void unload() { @@ -222,30 +217,3 @@ struct SoftbodyRectangle { delete [] pointsVertices; } }; - -EM_BOOL onMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) { - SoftbodyRectangle* rectangle = (SoftbodyRectangle*)userData; - rectangle->hasLastPositionChanged = true; - rectangle->lastMousePosition = Vector2(static_cast(mouseEvent->targetX), static_cast(600 - mouseEvent->targetY)); - return true; -} - -EM_BOOL onMouseDown(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) { - SoftbodyRectangle* rectangle = (SoftbodyRectangle*)userData; - - for (int32 v = 0; v < rectangle->pointsMesh.numVertices; v++) { - auto pointMass = &rectangle->updateData[v]; - if (pointMass->isHovered) { - rectangle->draggedVertex = pointMass; - break; - } - } - - return true; -} - -EM_BOOL onMouseUp(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) { - SoftbodyRectangle* rectangle = (SoftbodyRectangle*)userData; - rectangle->draggedVertex = NULL; - return true; -} diff --git a/2d/softbody/softbody_2/dist/output.js b/2d/softbody/softbody_2/dist/output.js index 51df416..4f59242 100644 --- a/2d/softbody/softbody_2/dist/output.js +++ b/2d/softbody/softbody_2/dist/output.js @@ -15,6 +15,9 @@ // can continue to use Module afterwards as well. var Module = typeof Module !== 'undefined' ? Module : {}; +// See https://caniuse.com/mdn-javascript_builtins_object_assign +var objAssign = Object.assign; + // --pre-jses are emitted after the Module integration code, so that they can // refer to Module (if they choose; they can also define Module) // {{PRE_JSES}} @@ -24,17 +27,11 @@ var Module = typeof Module !== 'undefined' ? Module : {}; // we collect those properties and reapply _after_ we configure // the current environment's defaults to avoid having to be so // defensive during initialization. -var moduleOverrides = {}; -var key; -for (key in Module) { - if (Module.hasOwnProperty(key)) { - moduleOverrides[key] = Module[key]; - } -} +var moduleOverrides = objAssign({}, Module); var arguments_ = []; var thisProgram = './this.program'; -var quit_ = function(status, toThrow) { +var quit_ = (status, toThrow) => { throw toThrow; }; @@ -77,15 +74,16 @@ var read_, // this may no longer be needed under node. function logExceptionOnExit(e) { if (e instanceof ExitStatus) return; - var toLog = e; + let toLog = e; if (e && typeof e === 'object' && e.stack) { toLog = [e, e.stack]; } err('exiting due to exception: ' + toLog); } -var nodeFS; +var fs; var nodePath; +var requireNodeFS; if (ENVIRONMENT_IS_NODE) { if (!(typeof process === 'object' && typeof require === 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); @@ -98,11 +96,20 @@ if (ENVIRONMENT_IS_NODE) { // include: node_shell_read.js +requireNodeFS = function() { + // Use nodePath as the indicator for these not being initialized, + // since in some environments a global fs may have already been + // created. + if (!nodePath) { + fs = require('fs'); + nodePath = require('path'); + } +} + read_ = function shell_read(filename, binary) { - if (!nodeFS) nodeFS = require('fs'); - if (!nodePath) nodePath = require('path'); + requireNodeFS(); filename = nodePath['normalize'](filename); - return nodeFS['readFileSync'](filename, binary ? null : 'utf8'); + return fs.readFileSync(filename, binary ? null : 'utf8'); }; readBinary = function readBinary(filename) { @@ -115,10 +122,9 @@ readBinary = function readBinary(filename) { }; readAsync = function readAsync(filename, onload, onerror) { - if (!nodeFS) nodeFS = require('fs'); - if (!nodePath) nodePath = require('path'); + requireNodeFS(); filename = nodePath['normalize'](filename); - nodeFS['readFile'](filename, function(err, data) { + fs.readFile(filename, function(err, data) { if (err) onerror(err); else onload(data.buffer); }); @@ -149,7 +155,7 @@ readAsync = function readAsync(filename, onload, onerror) { // See https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode process['on']('unhandledRejection', function(reason) { throw reason; }); - quit_ = function(status, toThrow) { + quit_ = (status, toThrow) => { if (keepRuntimeAlive()) { process['exitCode'] = status; throw toThrow; @@ -172,7 +178,7 @@ if (ENVIRONMENT_IS_SHELL) { } readBinary = function readBinary(f) { - var data; + let data; if (typeof readbuffer === 'function') { return new Uint8Array(readbuffer(f)); } @@ -182,7 +188,7 @@ if (ENVIRONMENT_IS_SHELL) { }; readAsync = function readAsync(f, onload, onerror) { - setTimeout(function() { onload(readBinary(f)); }, 0); + setTimeout(() => onload(readBinary(f)), 0); }; if (typeof scriptArgs != 'undefined') { @@ -192,7 +198,7 @@ if (ENVIRONMENT_IS_SHELL) { } if (typeof quit === 'function') { - quit_ = function(status, toThrow) { + quit_ = (status, toThrow) => { logExceptionOnExit(toThrow); quit(status); }; @@ -233,7 +239,6 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { // Differentiate the Web Worker from the Node Worker case, as reading must // be done differently. { - // include: web_or_worker_shell_read.js @@ -272,7 +277,7 @@ if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { // end include: web_or_worker_shell_read.js } - setWindowTitle = function(title) { document.title = title }; + setWindowTitle = (title) => document.title = title; } else { throw new Error('environment detection error'); @@ -282,11 +287,7 @@ var out = Module['print'] || console.log.bind(console); var err = Module['printErr'] || console.warn.bind(console); // Merge back in the overrides -for (key in moduleOverrides) { - if (moduleOverrides.hasOwnProperty(key)) { - Module[key] = moduleOverrides[key]; - } -} +objAssign(Module, moduleOverrides); // Free the object hierarchy contained in the overrides, this lets the GC // reclaim data used e.g. in memoryInitializerRequest, which is a large typed array. moduleOverrides = null; @@ -396,10 +397,10 @@ function getNativeTypeSize(type) { case 'float': return 4; case 'double': return 8; default: { - if (type[type.length-1] === '*') { + if (type[type.length - 1] === '*') { return POINTER_SIZE; } else if (type[0] === 'i') { - var bits = Number(type.substr(1)); + const bits = Number(type.substr(1)); assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type); return bits / 8; } else { @@ -694,7 +695,7 @@ var EXITSTATUS; /** @type {function(*, string=)} */ function assert(condition, text) { if (!condition) { - abort('Assertion failed: ' + text); + abort('Assertion failed' + (text ? ': ' + text : '')); } } @@ -2095,21 +2096,6 @@ var ASM_CONSTS = { return 0; } - function _emscripten_set_mousedown_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { - registerMouseEventCallback(target, userData, useCapture, callbackfunc, 5, "mousedown", targetThread); - return 0; - } - - function _emscripten_set_mousemove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { - registerMouseEventCallback(target, userData, useCapture, callbackfunc, 8, "mousemove", targetThread); - return 0; - } - - function _emscripten_set_mouseup_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) { - registerMouseEventCallback(target, userData, useCapture, callbackfunc, 6, "mouseup", targetThread); - return 0; - } - function __webgl_enable_ANGLE_instanced_arrays(ctx) { // Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2. var ext = ctx.getExtension('ANGLE_instanced_arrays'); @@ -2449,20 +2435,6 @@ var ASM_CONSTS = { return _emscripten_webgl_do_create_context(a0,a1); } - function _emscripten_webgl_do_get_current_context() { - return GL.currentContext ? GL.currentContext.handle : 0; - } - function _emscripten_webgl_get_current_context( - ) { - return _emscripten_webgl_do_get_current_context(); - } - Module["_emscripten_webgl_get_current_context"] = _emscripten_webgl_get_current_context; - - function _emscripten_webgl_make_context_current(contextHandle) { - var success = GL.makeContextCurrent(contextHandle); - return success ? 0 : -5; - } - Module["_emscripten_webgl_make_context_current"] = _emscripten_webgl_make_context_current; function _emscripten_webgl_destroy_context(contextHandle) { if (GL.currentContext == contextHandle) GL.currentContext = 0; GL.deleteContext(contextHandle); @@ -2484,6 +2456,10 @@ var ASM_CONSTS = { } + function _emscripten_webgl_make_context_current(contextHandle) { + var success = GL.makeContextCurrent(contextHandle); + return success ? 0 : -5; + } var SYSCALLS = {mappings:{},buffers:[null,[],[]],printChar:function(stream, curr) { var buffer = SYSCALLS.buffers[stream]; @@ -3074,9 +3050,6 @@ var asmLibraryArg = { "emscripten_resize_heap": _emscripten_resize_heap, "emscripten_set_canvas_element_size": _emscripten_set_canvas_element_size, "emscripten_set_click_callback_on_thread": _emscripten_set_click_callback_on_thread, - "emscripten_set_mousedown_callback_on_thread": _emscripten_set_mousedown_callback_on_thread, - "emscripten_set_mousemove_callback_on_thread": _emscripten_set_mousemove_callback_on_thread, - "emscripten_set_mouseup_callback_on_thread": _emscripten_set_mouseup_callback_on_thread, "emscripten_webgl_create_context": _emscripten_webgl_create_context, "emscripten_webgl_destroy_context": _emscripten_webgl_destroy_context, "emscripten_webgl_init_context_attributes": _emscripten_webgl_init_context_attributes, @@ -3133,15 +3106,6 @@ var ___errno_location = Module["___errno_location"] = createExportWrapper("__err /** @type {function(...*):?} */ var _fflush = Module["_fflush"] = createExportWrapper("fflush"); -/** @type {function(...*):?} */ -var stackSave = Module["stackSave"] = createExportWrapper("stackSave"); - -/** @type {function(...*):?} */ -var stackRestore = Module["stackRestore"] = createExportWrapper("stackRestore"); - -/** @type {function(...*):?} */ -var stackAlloc = Module["stackAlloc"] = createExportWrapper("stackAlloc"); - /** @type {function(...*):?} */ var _emscripten_stack_init = Module["_emscripten_stack_init"] = function() { return (_emscripten_stack_init = Module["_emscripten_stack_init"] = Module["asm"]["emscripten_stack_init"]).apply(null, arguments); @@ -3157,6 +3121,15 @@ var _emscripten_stack_get_end = Module["_emscripten_stack_get_end"] = function() return (_emscripten_stack_get_end = Module["_emscripten_stack_get_end"] = Module["asm"]["emscripten_stack_get_end"]).apply(null, arguments); }; +/** @type {function(...*):?} */ +var stackSave = Module["stackSave"] = createExportWrapper("stackSave"); + +/** @type {function(...*):?} */ +var stackRestore = Module["stackRestore"] = createExportWrapper("stackRestore"); + +/** @type {function(...*):?} */ +var stackAlloc = Module["stackAlloc"] = createExportWrapper("stackAlloc"); + /** @type {function(...*):?} */ var _malloc = Module["_malloc"] = createExportWrapper("malloc"); @@ -3242,7 +3215,10 @@ if (!Object.getOwnPropertyDescriptor(Module, "Protocols")) Module["Protocols"] = if (!Object.getOwnPropertyDescriptor(Module, "Sockets")) Module["Sockets"] = function() { abort("'Sockets' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "getRandomDevice")) Module["getRandomDevice"] = function() { abort("'getRandomDevice' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "traverseStack")) Module["traverseStack"] = function() { abort("'traverseStack' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)") }; +if (!Object.getOwnPropertyDescriptor(Module, "convertFrameToPC")) Module["convertFrameToPC"] = function() { abort("'convertFrameToPC' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "UNWIND_CACHE")) Module["UNWIND_CACHE"] = function() { abort("'UNWIND_CACHE' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)") }; +if (!Object.getOwnPropertyDescriptor(Module, "saveInUnwindCache")) Module["saveInUnwindCache"] = function() { abort("'saveInUnwindCache' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)") }; +if (!Object.getOwnPropertyDescriptor(Module, "convertPCtoSourceLocation")) Module["convertPCtoSourceLocation"] = function() { abort("'convertPCtoSourceLocation' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "readAsmConstArgsArray")) Module["readAsmConstArgsArray"] = function() { abort("'readAsmConstArgsArray' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "readAsmConstArgs")) Module["readAsmConstArgs"] = function() { abort("'readAsmConstArgs' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)") }; if (!Object.getOwnPropertyDescriptor(Module, "mainThreadEM_ASM")) Module["mainThreadEM_ASM"] = function() { abort("'mainThreadEM_ASM' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)") }; diff --git a/2d/softbody/softbody_2/dist/output.wasm b/2d/softbody/softbody_2/dist/output.wasm index 85d82ce..8710d1a 100755 Binary files a/2d/softbody/softbody_2/dist/output.wasm and b/2d/softbody/softbody_2/dist/output.wasm differ -- cgit v1.2.1