@@ -70,7 +70,7 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
-
+
diff --git a/2d/_collisions/pill_line.html.content b/2d/_collisions/pill_line.html.content
index ce779d5..f91b8d9 100644
--- a/2d/_collisions/pill_line.html.content
+++ b/2d/_collisions/pill_line.html.content
@@ -21,7 +21,7 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
@@ -70,7 +70,7 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
-
+
diff --git a/2d/_collisions/pill_pill.html.content b/2d/_collisions/pill_pill.html.content
index 385ae3c..a359715 100644
--- a/2d/_collisions/pill_pill.html.content
+++ b/2d/_collisions/pill_pill.html.content
@@ -21,7 +21,7 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
-
+
diff --git a/2d/_collisions/polygon_polygon.html.content b/2d/_collisions/polygon_polygon.html.content
index 969ce65..820fcbc 100644
--- a/2d/_collisions/polygon_polygon.html.content
+++ b/2d/_collisions/polygon_polygon.html.content
@@ -23,7 +23,7 @@
Live Example
-
+
diff --git a/2d/_collisions/polygon_polygon/dist/output.js b/2d/_collisions/polygon_polygon/dist/output.js
index 42a4ed5..e1dfee3 100644
--- a/2d/_collisions/polygon_polygon/dist/output.js
+++ b/2d/_collisions/polygon_polygon/dist/output.js
@@ -609,7 +609,7 @@ if (typeof WebAssembly !== 'object') {
function setValue(ptr, value, type, noSafe) {
type = type || 'i8';
if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
- switch (type) {
+ switch(type) {
case 'i1': HEAP8[((ptr)>>0)] = value; break;
case 'i8': HEAP8[((ptr)>>0)] = value; break;
case 'i16': HEAP16[((ptr)>>1)] = value; break;
@@ -627,7 +627,7 @@ function setValue(ptr, value, type, noSafe) {
function getValue(ptr, type, noSafe) {
type = type || 'i8';
if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
- switch (type) {
+ switch(type) {
case 'i1': return HEAP8[((ptr)>>0)];
case 'i8': return HEAP8[((ptr)>>0)];
case 'i16': return HEAP16[((ptr)>>1)];
@@ -808,7 +808,7 @@ function UTF8ArrayToString(heap, idx, maxBytesToRead) {
if ((u0 & 0xF0) == 0xE0) {
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
} else {
- if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
+ if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!');
u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heap[idx++] & 63);
}
@@ -884,7 +884,7 @@ function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
heap[outIdx++] = 0x80 | (u & 63);
} else {
if (outIdx + 3 >= endIdx) break;
- if (u >= 0x200000) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x1FFFFF).');
+ if (u >= 0x200000) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).');
heap[outIdx++] = 0xF0 | (u >> 18);
heap[outIdx++] = 0x80 | ((u >> 12) & 63);
heap[outIdx++] = 0x80 | ((u >> 6) & 63);
@@ -1252,12 +1252,12 @@ function checkStackCookie() {
// include: runtime_assertions.js
-// Endianness check
+// Endianness check (note: assumes compiler arch was little-endian)
(function() {
var h16 = new Int16Array(1);
var h8 = new Int8Array(h16.buffer);
h16[0] = 0x6373;
- if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -s SUPPORT_BIG_ENDIAN=1 to bypass)';
+ if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian!';
})();
function abortFnPtrError(ptr, sig) {
@@ -1274,6 +1274,8 @@ var __ATPOSTRUN__ = []; // functions called after the main() is called
var runtimeInitialized = false;
var runtimeExited = false;
+__ATINIT__.push({ func: function() { ___wasm_call_ctors() } });
+
function preRun() {
if (Module['preRun']) {
@@ -1290,7 +1292,6 @@ function initRuntime() {
checkStackCookie();
assert(!runtimeInitialized);
runtimeInitialized = true;
-
callRuntimeCallbacks(__ATINIT__);
}
@@ -1615,8 +1616,6 @@ function createWasm() {
wasmTable = Module['asm']['__indirect_function_table'];
assert(wasmTable, "table not found in wasm exports");
- addOnInit(Module['asm']['__wasm_call_ctors']);
-
removeRunDependency('wasm-instantiate');
}
// we can't run yet (except in a pthread, where we have a custom sync instantiator)
@@ -1638,8 +1637,7 @@ function createWasm() {
function instantiateArrayBuffer(receiver) {
return getBinaryPromise().then(function(binary) {
- var result = WebAssembly.instantiate(binary, info);
- return result;
+ return WebAssembly.instantiate(binary, info);
}).then(receiver, function(reason) {
err('failed to asynchronously prepare wasm: ' + reason);
@@ -1706,8 +1704,12 @@ var ASM_CONSTS = {
+ function abortStackOverflow(allocSize) {
+ abort('Stack overflow! Attempted to allocate ' + allocSize + ' bytes on the stack, but stack has only ' + (_emscripten_stack_get_free() + allocSize) + ' bytes available!');
+ }
+
function callRuntimeCallbacks(callbacks) {
- while (callbacks.length > 0) {
+ while(callbacks.length > 0) {
var callback = callbacks.shift();
if (typeof callback == 'function') {
callback(Module); // Pass the module as the first argument.
@@ -1758,11 +1760,6 @@ var ASM_CONSTS = {
return error.stack.toString();
}
- var runtimeKeepaliveCounter=0;
- function keepRuntimeAlive() {
- return noExitRuntime || runtimeKeepaliveCounter > 0;
- }
-
function stackTrace() {
var js = jsStackTrace();
if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace']();
@@ -1786,6 +1783,10 @@ var ASM_CONSTS = {
return requestAnimationFrame(tick);
}
+ function _emscripten_get_heap_size() {
+ return HEAPU8.length;
+ }
+
function emscripten_realloc_buffer(size) {
try {
// round size grow request up to wasm page size (fixed 64KB per spec)
@@ -1799,8 +1800,7 @@ var ASM_CONSTS = {
// anyhow)
}
function _emscripten_resize_heap(requestedSize) {
- var oldSize = HEAPU8.length;
- requestedSize = requestedSize >>> 0;
+ var oldSize = _emscripten_get_heap_size();
// With pthreads, races can happen (another thread might increase the size in between), so return a failure, and let the caller retry.
assert(requestedSize > oldSize);
@@ -1827,7 +1827,7 @@ var ASM_CONSTS = {
// Loop through potential heap size increases. If we attempt a too eager reservation that fails, cut down on the
// attempted size and reserve a smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
- for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
+ for(var cutDown = 1; cutDown <= 4; cutDown *= 2) {
var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth
// but limit overreserving (default to capping at +96MB overgrowth at most)
overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 );
@@ -1845,7 +1845,7 @@ var ASM_CONSTS = {
}
var JSEvents={inEventHandler:0,removeAllEventListeners:function() {
- for (var i = JSEvents.eventHandlers.length-1; i >= 0; --i) {
+ for(var i = JSEvents.eventHandlers.length-1; i >= 0; --i) {
JSEvents._removeHandler(i);
}
JSEvents.eventHandlers = [];
@@ -1859,13 +1859,13 @@ var ASM_CONSTS = {
function arraysHaveEqualContent(arrA, arrB) {
if (arrA.length != arrB.length) return false;
- for (var i in arrA) {
+ for(var i in arrA) {
if (arrA[i] != arrB[i]) return false;
}
return true;
}
// Test if the given call was already queued, and if so, don't add it again.
- for (var i in JSEvents.deferredCalls) {
+ for(var i in JSEvents.deferredCalls) {
var call = JSEvents.deferredCalls[i];
if (call.targetFunction == targetFunction && arraysHaveEqualContent(call.argsList, argsList)) {
return;
@@ -1879,7 +1879,7 @@ var ASM_CONSTS = {
JSEvents.deferredCalls.sort(function(x,y) { return x.precedence < y.precedence; });
},removeDeferredCalls:function(targetFunction) {
- for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
+ for(var i = 0; i < JSEvents.deferredCalls.length; ++i) {
if (JSEvents.deferredCalls[i].targetFunction == targetFunction) {
JSEvents.deferredCalls.splice(i, 1);
--i;
@@ -1891,14 +1891,14 @@ var ASM_CONSTS = {
if (!JSEvents.canPerformEventHandlerRequests()) {
return;
}
- for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
+ for(var i = 0; i < JSEvents.deferredCalls.length; ++i) {
var call = JSEvents.deferredCalls[i];
JSEvents.deferredCalls.splice(i, 1);
--i;
call.targetFunction.apply(null, call.argsList);
}
},eventHandlers:[],removeAllHandlersOnTarget:function(target, eventTypeString) {
- for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
+ for(var i = 0; i < JSEvents.eventHandlers.length; ++i) {
if (JSEvents.eventHandlers[i].target == target &&
(!eventTypeString || eventTypeString == JSEvents.eventHandlers[i].eventTypeString)) {
JSEvents._removeHandler(i--);
@@ -1929,7 +1929,7 @@ var ASM_CONSTS = {
JSEvents.eventHandlers.push(eventHandler);
JSEvents.registerRemoveEventListeners();
} else {
- for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
+ for(var i = 0; i < JSEvents.eventHandlers.length; ++i) {
if (JSEvents.eventHandlers[i].target == eventHandler.target
&& JSEvents.eventHandlers[i].eventTypeString == eventHandler.eventTypeString) {
JSEvents._removeHandler(i--);
@@ -2074,7 +2074,7 @@ var ASM_CONSTS = {
// Closure is expected to be allowed to minify the '.multiDrawWebgl' property, so not accessing it quoted.
return !!(ctx.multiDrawWebgl = ctx.getExtension('WEBGL_multi_draw'));
}
- var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode) {
+ var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},timerQueriesEXT:[],queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],programInfos:{},stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode) {
if (!GL.lastError) {
GL.lastError = errorCode;
}
@@ -2085,7 +2085,7 @@ var ASM_CONSTS = {
}
return ret;
},MAX_TEMP_BUFFER_SIZE:2097152,numTempVertexBuffersPerSize:64,log2ceilLookup:function(i) {
- return 32 - Math.clz32(i === 0 ? 0 : i - 1);
+ return 32 - Math.clz32(i-1);
},generateTempBuffers:function(quads, context) {
var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
context.tempVertexBufferCounters1 = [];
@@ -2213,19 +2213,6 @@ var ASM_CONSTS = {
}
},createContext:function(canvas, webGLContextAttributes) {
- // BUG: Workaround Safari WebGL issue: After successfully acquiring WebGL context on a canvas,
- // calling .getContext() will always return that context independent of which 'webgl' or 'webgl2'
- // context version was passed. See https://bugs.webkit.org/show_bug.cgi?id=222758 and
- // https://github.com/emscripten-core/emscripten/issues/13295.
- // TODO: Once the bug is fixed and shipped in Safari, adjust the Safari version field in above check.
- if (!canvas.getContextSafariWebGL2Fixed) {
- canvas.getContextSafariWebGL2Fixed = canvas.getContext;
- canvas.getContext = function(ver, attrs) {
- var gl = canvas.getContextSafariWebGL2Fixed(ver, attrs);
- return ((ver == 'webgl') == (gl instanceof WebGLRenderingContext)) ? gl : null;
- }
- }
-
var ctx =
(webGLContextAttributes.majorVersion > 1)
?
@@ -2298,21 +2285,7 @@ var ASM_CONSTS = {
__webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);
__webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);
- // On WebGL 2, EXT_disjoint_timer_query is replaced with an alternative
- // that's based on core APIs, and exposes only the queryCounterEXT()
- // entrypoint.
- if (context.version >= 2) {
- GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query_webgl2");
- }
-
- // However, Firefox exposes the WebGL 1 version on WebGL 2 as well and
- // thus we look for the WebGL 1 version again if the WebGL 2 version
- // isn't present. https://bugzilla.mozilla.org/show_bug.cgi?id=1328882
- if (context.version < 2 || !GLctx.disjointTimerQueryExt)
- {
- GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
- }
-
+ GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
__webgl_enable_WEBGL_multi_draw(GLctx);
// .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
@@ -2324,6 +2297,49 @@ var ASM_CONSTS = {
GLctx.getExtension(ext);
}
});
+ },populateUniformTable:function(program) {
+ var p = GL.programs[program];
+ var ptable = GL.programInfos[program] = {
+ uniforms: {},
+ maxUniformLength: 0, // This is eagerly computed below, since we already enumerate all uniforms anyway.
+ maxAttributeLength: -1, // This is lazily computed and cached, computed when/if first asked, "-1" meaning not computed yet.
+ maxUniformBlockNameLength: -1 // Lazily computed as well
+ };
+
+ var utable = ptable.uniforms;
+ // A program's uniform table maps the string name of an uniform to an integer location of that uniform.
+ // The global GL.uniforms map maps integer locations to WebGLUniformLocations.
+ var numUniforms = GLctx.getProgramParameter(p, 0x8B86/*GL_ACTIVE_UNIFORMS*/);
+ for (var i = 0; i < numUniforms; ++i) {
+ var u = GLctx.getActiveUniform(p, i);
+
+ var name = u.name;
+ ptable.maxUniformLength = Math.max(ptable.maxUniformLength, name.length+1);
+
+ // If we are dealing with an array, e.g. vec4 foo[3], strip off the array index part to canonicalize that "foo", "foo[]",
+ // and "foo[0]" will mean the same. Loop below will populate foo[1] and foo[2].
+ if (name.slice(-1) == ']') {
+ name = name.slice(0, name.lastIndexOf('['));
+ }
+
+ // Optimize memory usage slightly: If we have an array of uniforms, e.g. 'vec3 colors[3];', then
+ // only store the string 'colors' in utable, and 'colors[0]', 'colors[1]' and 'colors[2]' will be parsed as 'colors'+i.
+ // Note that for the GL.uniforms table, we still need to fetch the all WebGLUniformLocations for all the indices.
+ var loc = GLctx.getUniformLocation(p, name);
+ if (loc) {
+ var id = GL.getNewId(GL.uniforms);
+ utable[name] = [u.size, id];
+ GL.uniforms[id] = loc;
+
+ for (var j = 1; j < u.size; ++j) {
+ var n = name + '['+j+']';
+ loc = GLctx.getUniformLocation(p, n);
+ id = GL.getNewId(GL.uniforms);
+
+ GL.uniforms[id] = loc;
+ }
+ }
+ }
}};
var __emscripten_webgl_power_preferences=['default', 'low-power', 'high-performance'];
@@ -2370,7 +2386,7 @@ var ASM_CONSTS = {
function _emscripten_webgl_init_context_attributes(attributes) {
assert(attributes);
var a = attributes >> 2;
- for (var i = 0; i < (56>>2); ++i) {
+ for(var i = 0; i < (56>>2); ++i) {
HEAP32[a+i] = 0;
}
@@ -2434,7 +2450,8 @@ var ASM_CONSTS = {
}
function _glAttachShader(program, shader) {
- GLctx.attachShader(GL.programs[program], GL.shaders[shader]);
+ GLctx.attachShader(GL.programs[program],
+ GL.shaders[shader]);
}
function _glBindBuffer(target, buffer) {
@@ -2494,11 +2511,7 @@ var ASM_CONSTS = {
function _glCreateProgram() {
var id = GL.getNewId(GL.programs);
var program = GLctx.createProgram();
- // Store additional information needed for each shader program:
program.name = id;
- // Lazy cache results of glGetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH/GL_ACTIVE_ATTRIBUTE_MAX_LENGTH/GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH)
- program.maxUniformLength = program.maxAttributeLength = program.maxUniformBlockNameLength = 0;
- program.uniformIdCounter = 1;
GL.programs[id] = program;
return id;
}
@@ -2506,7 +2519,6 @@ var ASM_CONSTS = {
function _glCreateShader(shaderType) {
var id = GL.getNewId(GL.shaders);
GL.shaders[id] = GLctx.createShader(shaderType);
-
return id;
}
@@ -2540,6 +2552,7 @@ var ASM_CONSTS = {
GLctx.deleteProgram(program);
program.name = 0;
GL.programs[id] = null;
+ GL.programInfos[id] = null;
}
function _glDeleteShader(id) {
@@ -2632,35 +2645,42 @@ var ASM_CONSTS = {
return;
}
- program = GL.programs[program];
+ var ptable = GL.programInfos[program];
+ if (!ptable) {
+ GL.recordError(0x502 /* GL_INVALID_OPERATION */);
+ return;
+ }
if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
- var log = GLctx.getProgramInfoLog(program);
+ var log = GLctx.getProgramInfoLog(GL.programs[program]);
if (log === null) log = '(unknown error)';
HEAP32[((p)>>2)] = log.length + 1;
} else if (pname == 0x8B87 /* GL_ACTIVE_UNIFORM_MAX_LENGTH */) {
- if (!program.maxUniformLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8B86/*GL_ACTIVE_UNIFORMS*/); ++i) {
- program.maxUniformLength = Math.max(program.maxUniformLength, GLctx.getActiveUniform(program, i).name.length+1);
- }
- }
- HEAP32[((p)>>2)] = program.maxUniformLength;
+ HEAP32[((p)>>2)] = ptable.maxUniformLength;
} else if (pname == 0x8B8A /* GL_ACTIVE_ATTRIBUTE_MAX_LENGTH */) {
- if (!program.maxAttributeLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/); ++i) {
- program.maxAttributeLength = Math.max(program.maxAttributeLength, GLctx.getActiveAttrib(program, i).name.length+1);
+ if (ptable.maxAttributeLength == -1) {
+ program = GL.programs[program];
+ var numAttribs = GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/);
+ ptable.maxAttributeLength = 0; // Spec says if there are no active attribs, 0 must be returned.
+ for (var i = 0; i < numAttribs; ++i) {
+ var activeAttrib = GLctx.getActiveAttrib(program, i);
+ ptable.maxAttributeLength = Math.max(ptable.maxAttributeLength, activeAttrib.name.length+1);
}
}
- HEAP32[((p)>>2)] = program.maxAttributeLength;
+ HEAP32[((p)>>2)] = ptable.maxAttributeLength;
} else if (pname == 0x8A35 /* GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH */) {
- if (!program.maxUniformBlockNameLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/); ++i) {
- program.maxUniformBlockNameLength = Math.max(program.maxUniformBlockNameLength, GLctx.getActiveUniformBlockName(program, i).length+1);
+ if (ptable.maxUniformBlockNameLength == -1) {
+ program = GL.programs[program];
+ var numBlocks = GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/);
+ ptable.maxUniformBlockNameLength = 0;
+ for (var i = 0; i < numBlocks; ++i) {
+ var activeBlockName = GLctx.getActiveUniformBlockName(program, i);
+ ptable.maxUniformBlockNameLength = Math.max(ptable.maxUniformBlockNameLength, activeBlockName.length+1);
}
}
- HEAP32[((p)>>2)] = program.maxUniformBlockNameLength;
+ HEAP32[((p)>>2)] = ptable.maxUniformBlockNameLength;
} else {
- HEAP32[((p)>>2)] = GLctx.getProgramParameter(program, pname);
+ HEAP32[((p)>>2)] = GLctx.getProgramParameter(GL.programs[program], pname);
}
}
@@ -2703,91 +2723,27 @@ var ASM_CONSTS = {
return parseInt(str);
}
function _glGetUniformLocation(program, name) {
- // Returns the index of '[' character in an uniform that represents an array of uniforms (e.g. colors[10])
- // Closure does counterproductive inlining: https://github.com/google/closure-compiler/issues/3203, so prevent
- // inlining manually.
- /** @noinline */
- function getLeftBracePos(name) {
- return name.slice(-1) == ']' && name.lastIndexOf('[');
- }
-
name = UTF8ToString(name);
- program = GL.programs[program];
- var uniformLocsById = program.uniformLocsById; // Maps GLuint -> WebGLUniformLocation
- var uniformSizeAndIdsByName = program.uniformSizeAndIdsByName; // Maps name -> [uniform array length, GLuint]
- var i, j;
var arrayIndex = 0;
- var uniformBaseName = name;
-
- // Invariant: when populating integer IDs for uniform locations, we must maintain the precondition that
- // arrays reside in contiguous addresses, i.e. for a 'vec4 colors[10];', colors[4] must be at location colors[0]+4.
- // However, user might call glGetUniformLocation(program, "colors") for an array, so we cannot discover based on the user
- // input arguments whether the uniform we are dealing with is an array. The only way to discover which uniforms are arrays
- // is to enumerate over all the active uniforms in the program.
- var leftBrace = getLeftBracePos(name);
-
- // On the first time invocation of glGetUniformLocation on this shader program:
- // initialize cache data structures and discover which uniforms are arrays.
- if (!uniformLocsById) {
- // maps GLint integer locations to WebGLUniformLocations
- program.uniformLocsById = uniformLocsById = {};
- // maps integer locations back to uniform name strings, so that we can lazily fetch uniform array locations
- program.uniformArrayNamesById = {};
-
- for (i = 0; i < GLctx.getProgramParameter(program, 0x8B86/*GL_ACTIVE_UNIFORMS*/); ++i) {
- var u = GLctx.getActiveUniform(program, i);
- var nm = u.name;
- var sz = u.size;
- var lb = getLeftBracePos(nm);
- var arrayName = lb > 0 ? nm.slice(0, lb) : nm;
-
- // Assign a new location.
- var id = program.uniformIdCounter;
- program.uniformIdCounter += sz;
- // Eagerly get the location of the uniformArray[0] base element.
- // The remaining indices >0 will be left for lazy evaluation to
- // improve performance. Those may never be needed to fetch, if the
- // application fills arrays always in full starting from the first
- // element of the array.
- uniformSizeAndIdsByName[arrayName] = [sz, id];
-
- // Store placeholder integers in place that highlight that these
- // >0 index locations are array indices pending population.
- for(j = 0; j < sz; ++j) {
- uniformLocsById[id] = j;
- program.uniformArrayNamesById[id++] = arrayName;
- }
- }
- }
-
// If user passed an array accessor "[index]", parse the array index off the accessor.
- if (leftBrace > 0) {
- arrayIndex = jstoi_q(name.slice(leftBrace + 1)) >>> 0; // "index]", coerce parseInt(']') with >>>0 to treat "foo[]" as "foo[0]" and foo[-1] as unsigned out-of-bounds.
- uniformBaseName = name.slice(0, leftBrace);
+ if (name[name.length - 1] == ']') {
+ var leftBrace = name.lastIndexOf('[');
+ arrayIndex = name[leftBrace+1] != ']' ? jstoi_q(name.slice(leftBrace + 1)) : 0; // "index]", parseInt will ignore the ']' at the end; but treat "foo[]" as "foo[0]"
+ name = name.slice(0, leftBrace);
}
- // Have we cached the location of this uniform before?
- var sizeAndId = uniformSizeAndIdsByName[uniformBaseName]; // A pair [array length, GLint of the uniform location]
-
- // If an uniform with this name exists, and if its index is within the array limits (if it's even an array),
- // query the WebGLlocation, or return an existing cached location.
- if (sizeAndId && arrayIndex < sizeAndId[0]) {
- arrayIndex += sizeAndId[1]; // Add the base location of the uniform to the array index offset.
- if ((uniformLocsById[arrayIndex] = uniformLocsById[arrayIndex] || GLctx.getUniformLocation(program, name))) {
- return arrayIndex;
- }
+ var uniformInfo = GL.programInfos[program] && GL.programInfos[program].uniforms[name]; // returns pair [ dimension_of_uniform_array, uniform_location ]
+ if (uniformInfo && arrayIndex >= 0 && arrayIndex < uniformInfo[0]) { // Check if user asked for an out-of-bounds element, i.e. for 'vec4 colors[3];' user could ask for 'colors[10]' which should return -1.
+ return uniformInfo[1] + arrayIndex;
+ } else {
+ return -1;
}
- return -1;
}
function _glLinkProgram(program) {
- program = GL.programs[program];
- GLctx.linkProgram(program);
- // Invalidate earlier computed uniform->ID mappings, those have now become stale
- program.uniformLocsById = 0; // Mark as null-like so that glGetUniformLocation() knows to populate this again.
- program.uniformSizeAndIdsByName = {};
-
+ GLctx.linkProgram(GL.programs[program]);
+ GL.populateUniformTable(program);
}
function _glShaderSource(shader, count, string, length) {
@@ -2796,25 +2752,11 @@ var ASM_CONSTS = {
GLctx.shaderSource(GL.shaders[shader], source);
}
- function webglGetUniformLocation(location) {
- var p = GLctx.currentProgram;
- var webglLoc = p.uniformLocsById[location];
- // p.uniformLocsById[location] stores either an integer, or a WebGLUniformLocation.
-
- // If an integer, we have not yet bound the location, so do it now. The integer value specifies the array index
- // we should bind to.
- if (webglLoc >= 0) {
- p.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(p, p.uniformArrayNamesById[location] + (webglLoc > 0 ? '[' + webglLoc + ']' : ''));
- }
- // Else an already cached WebGLUniformLocation, return it.
- return webglLoc;
- }
-
var miniTempWebGLFloatBuffers=[];
function _glUniformMatrix4fv(location, count, transpose, value) {
if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible.
- GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*16);
+ GLctx.uniformMatrix4fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*16);
return;
}
@@ -2847,15 +2789,11 @@ var ASM_CONSTS = {
{
var view = HEAPF32.subarray((value)>>2, (value+count*64)>>2);
}
- GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, view);
+ GLctx.uniformMatrix4fv(GL.uniforms[location], !!transpose, view);
}
function _glUseProgram(program) {
- program = GL.programs[program];
- GLctx.useProgram(program);
- // Record the currently active program so that we can access the uniform
- // mapping table of that program.
- GLctx.currentProgram = program;
+ GLctx.useProgram(GL.programs[program]);
}
function _glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
@@ -3066,10 +3004,6 @@ if (!Object.getOwnPropertyDescriptor(Module, "ENV")) Module["ENV"] = function()
if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_CODES")) Module["ERRNO_CODES"] = function() { abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_MESSAGES")) Module["ERRNO_MESSAGES"] = function() { abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "setErrNo")) Module["setErrNo"] = function() { abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetPton4")) Module["inetPton4"] = function() { abort("'inetPton4' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetNtop4")) Module["inetNtop4"] = function() { abort("'inetNtop4' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetPton6")) Module["inetPton6"] = function() { abort("'inetPton6' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetNtop6")) Module["inetNtop6"] = function() { abort("'inetNtop6' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "readSockaddr")) Module["readSockaddr"] = function() { abort("'readSockaddr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "writeSockaddr")) Module["writeSockaddr"] = function() { abort("'writeSockaddr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "DNS")) Module["DNS"] = function() { abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
@@ -3093,12 +3027,7 @@ if (!Object.getOwnPropertyDescriptor(Module, "dynCallLegacy")) Module["dynCallLe
if (!Object.getOwnPropertyDescriptor(Module, "getDynCaller")) Module["getDynCaller"] = function() { abort("'getDynCaller' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "dynCall")) Module["dynCall"] = function() { abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "callRuntimeCallbacks")) Module["callRuntimeCallbacks"] = function() { abort("'callRuntimeCallbacks' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "runtimeKeepaliveCounter")) Module["runtimeKeepaliveCounter"] = function() { abort("'runtimeKeepaliveCounter' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "keepRuntimeAlive")) Module["keepRuntimeAlive"] = function() { abort("'keepRuntimeAlive' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "runtimeKeepalivePush")) Module["runtimeKeepalivePush"] = function() { abort("'runtimeKeepalivePush' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "runtimeKeepalivePop")) Module["runtimeKeepalivePop"] = function() { abort("'runtimeKeepalivePop' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "callUserCallback")) Module["callUserCallback"] = function() { abort("'callUserCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "maybeExit")) Module["maybeExit"] = function() { abort("'maybeExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Object.getOwnPropertyDescriptor(Module, "abortStackOverflow")) Module["abortStackOverflow"] = function() { abort("'abortStackOverflow' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "reallyNegative")) Module["reallyNegative"] = function() { abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "unSign")) Module["unSign"] = function() { abort("'unSign' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "reSign")) Module["reSign"] = function() { abort("'reSign' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
@@ -3199,7 +3128,6 @@ if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGet")) Module["emsc
if (!Object.getOwnPropertyDescriptor(Module, "computeUnpackAlignedImageSize")) Module["computeUnpackAlignedImageSize"] = function() { abort("'computeUnpackAlignedImageSize' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetTexPixelData")) Module["emscriptenWebGLGetTexPixelData"] = function() { abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetUniform")) Module["emscriptenWebGLGetUniform"] = function() { abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "webglGetUniformLocation")) Module["webglGetUniformLocation"] = function() { abort("'webglGetUniformLocation' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetVertexAttrib")) Module["emscriptenWebGLGetVertexAttrib"] = function() { abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetBufferBinding")) Module["emscriptenWebGLGetBufferBinding"] = function() { abort("'emscriptenWebGLGetBufferBinding' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLValidateMapBufferTarget")) Module["emscriptenWebGLValidateMapBufferTarget"] = function() { abort("'emscriptenWebGLValidateMapBufferTarget' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
@@ -3289,6 +3217,7 @@ function callMain(args) {
return;
} else if (e == 'unwind') {
// running an evented main loop, don't immediately exit
+ noExitRuntime = true;
return;
} else {
var toLog = e;
@@ -3398,19 +3327,17 @@ function checkUnflushedContent() {
/** @param {boolean|number=} implicit */
function exit(status, implicit) {
- EXITSTATUS = status;
-
checkUnflushedContent();
// if this is just main exit-ing implicitly, and the status is 0, then we
// don't need to do anything here and can just leave. if the status is
// non-zero, though, then we need to report it.
// (we may have warned about this earlier, if a situation justifies doing so)
- if (implicit && keepRuntimeAlive() && status === 0) {
+ if (implicit && noExitRuntime && status === 0) {
return;
}
- if (keepRuntimeAlive()) {
+ if (noExitRuntime) {
// if exit() was called, we may warn the user if the runtime isn't actually being shut down
if (!implicit) {
var msg = 'program exited (with status: ' + status + '), but EXIT_RUNTIME is not set, so halting execution but not exiting the runtime or preventing further async execution (build with EXIT_RUNTIME=1, if you want a true shutdown)';
@@ -3418,6 +3345,8 @@ function exit(status, implicit) {
}
} else {
+ EXITSTATUS = status;
+
exitRuntime();
if (Module['onExit']) Module['onExit'](status);
diff --git a/2d/_collisions/polygon_polygon/dist/output.wasm b/2d/_collisions/polygon_polygon/dist/output.wasm
index d008042..fd9538c 100755
Binary files a/2d/_collisions/polygon_polygon/dist/output.wasm and b/2d/_collisions/polygon_polygon/dist/output.wasm differ
diff --git a/2d/_collisions/polygon_polygon/main.cpp b/2d/_collisions/polygon_polygon/main.cpp
index b928f02..1633530 100644
--- a/2d/_collisions/polygon_polygon/main.cpp
+++ b/2d/_collisions/polygon_polygon/main.cpp
@@ -401,12 +401,12 @@ void update(float32 deltaTimeSeconds, void* userData) {
polygon->body.position.y = 0.f;
polygon->body.velocity = polygon->body.velocity - Vector2 { 0.f, 1.f } * (2 * (polygon->body.velocity.dot(Vector2 { 0.f, 1.f })));
}
- if (polygon->body.position.x >= 640.f) {
- polygon->body.position.x = 640.f;
+ if (polygon->body.position.x >= 800.f) {
+ polygon->body.position.x = 800.f;
polygon->body.velocity = polygon->body.velocity - Vector2 { -1.f, 0.f } * (2 * (polygon->body.velocity.dot(Vector2{ -1.f, 0.f })));
}
- if (polygon->body.position.y >= 480.f) {
- polygon->body.position.y = 480.f;
+ if (polygon->body.position.y >= 600.f) {
+ polygon->body.position.y = 600.f;
polygon->body.velocity = polygon->body.velocity - Vector2 { 0.f, -1.f } * (2 * (polygon->body.velocity.dot(Vector2 { 0.f, -1.f }))) ;
}
}
diff --git a/2d/_collisions/rectangle_line.html b/2d/_collisions/rectangle_line.html
index 8472763..e9720d1 100644
--- a/2d/_collisions/rectangle_line.html
+++ b/2d/_collisions/rectangle_line.html
@@ -18,14 +18,14 @@
🏀2D
@@ -107,7 +107,7 @@ Vector2 getNormalToLineSegment(LineSegment* segment) {
Live Example
-
+
diff --git a/2d/_collisions/rectangle_rectangle.html.content b/2d/_collisions/rectangle_rectangle.html.content
index 2cc5847..448fd33 100644
--- a/2d/_collisions/rectangle_rectangle.html.content
+++ b/2d/_collisions/rectangle_rectangle.html.content
@@ -58,7 +58,7 @@ Vector2 getNormalToLineSegment(LineSegment* segment) {
Live Example
-
+
diff --git a/2d/_collisions/rectangle_rectangle/dist/output.js b/2d/_collisions/rectangle_rectangle/dist/output.js
index 42a4ed5..e1dfee3 100644
--- a/2d/_collisions/rectangle_rectangle/dist/output.js
+++ b/2d/_collisions/rectangle_rectangle/dist/output.js
@@ -609,7 +609,7 @@ if (typeof WebAssembly !== 'object') {
function setValue(ptr, value, type, noSafe) {
type = type || 'i8';
if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
- switch (type) {
+ switch(type) {
case 'i1': HEAP8[((ptr)>>0)] = value; break;
case 'i8': HEAP8[((ptr)>>0)] = value; break;
case 'i16': HEAP16[((ptr)>>1)] = value; break;
@@ -627,7 +627,7 @@ function setValue(ptr, value, type, noSafe) {
function getValue(ptr, type, noSafe) {
type = type || 'i8';
if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
- switch (type) {
+ switch(type) {
case 'i1': return HEAP8[((ptr)>>0)];
case 'i8': return HEAP8[((ptr)>>0)];
case 'i16': return HEAP16[((ptr)>>1)];
@@ -808,7 +808,7 @@ function UTF8ArrayToString(heap, idx, maxBytesToRead) {
if ((u0 & 0xF0) == 0xE0) {
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
} else {
- if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
+ if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!');
u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heap[idx++] & 63);
}
@@ -884,7 +884,7 @@ function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
heap[outIdx++] = 0x80 | (u & 63);
} else {
if (outIdx + 3 >= endIdx) break;
- if (u >= 0x200000) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x1FFFFF).');
+ if (u >= 0x200000) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).');
heap[outIdx++] = 0xF0 | (u >> 18);
heap[outIdx++] = 0x80 | ((u >> 12) & 63);
heap[outIdx++] = 0x80 | ((u >> 6) & 63);
@@ -1252,12 +1252,12 @@ function checkStackCookie() {
// include: runtime_assertions.js
-// Endianness check
+// Endianness check (note: assumes compiler arch was little-endian)
(function() {
var h16 = new Int16Array(1);
var h8 = new Int8Array(h16.buffer);
h16[0] = 0x6373;
- if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -s SUPPORT_BIG_ENDIAN=1 to bypass)';
+ if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian!';
})();
function abortFnPtrError(ptr, sig) {
@@ -1274,6 +1274,8 @@ var __ATPOSTRUN__ = []; // functions called after the main() is called
var runtimeInitialized = false;
var runtimeExited = false;
+__ATINIT__.push({ func: function() { ___wasm_call_ctors() } });
+
function preRun() {
if (Module['preRun']) {
@@ -1290,7 +1292,6 @@ function initRuntime() {
checkStackCookie();
assert(!runtimeInitialized);
runtimeInitialized = true;
-
callRuntimeCallbacks(__ATINIT__);
}
@@ -1615,8 +1616,6 @@ function createWasm() {
wasmTable = Module['asm']['__indirect_function_table'];
assert(wasmTable, "table not found in wasm exports");
- addOnInit(Module['asm']['__wasm_call_ctors']);
-
removeRunDependency('wasm-instantiate');
}
// we can't run yet (except in a pthread, where we have a custom sync instantiator)
@@ -1638,8 +1637,7 @@ function createWasm() {
function instantiateArrayBuffer(receiver) {
return getBinaryPromise().then(function(binary) {
- var result = WebAssembly.instantiate(binary, info);
- return result;
+ return WebAssembly.instantiate(binary, info);
}).then(receiver, function(reason) {
err('failed to asynchronously prepare wasm: ' + reason);
@@ -1706,8 +1704,12 @@ var ASM_CONSTS = {
+ function abortStackOverflow(allocSize) {
+ abort('Stack overflow! Attempted to allocate ' + allocSize + ' bytes on the stack, but stack has only ' + (_emscripten_stack_get_free() + allocSize) + ' bytes available!');
+ }
+
function callRuntimeCallbacks(callbacks) {
- while (callbacks.length > 0) {
+ while(callbacks.length > 0) {
var callback = callbacks.shift();
if (typeof callback == 'function') {
callback(Module); // Pass the module as the first argument.
@@ -1758,11 +1760,6 @@ var ASM_CONSTS = {
return error.stack.toString();
}
- var runtimeKeepaliveCounter=0;
- function keepRuntimeAlive() {
- return noExitRuntime || runtimeKeepaliveCounter > 0;
- }
-
function stackTrace() {
var js = jsStackTrace();
if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace']();
@@ -1786,6 +1783,10 @@ var ASM_CONSTS = {
return requestAnimationFrame(tick);
}
+ function _emscripten_get_heap_size() {
+ return HEAPU8.length;
+ }
+
function emscripten_realloc_buffer(size) {
try {
// round size grow request up to wasm page size (fixed 64KB per spec)
@@ -1799,8 +1800,7 @@ var ASM_CONSTS = {
// anyhow)
}
function _emscripten_resize_heap(requestedSize) {
- var oldSize = HEAPU8.length;
- requestedSize = requestedSize >>> 0;
+ var oldSize = _emscripten_get_heap_size();
// With pthreads, races can happen (another thread might increase the size in between), so return a failure, and let the caller retry.
assert(requestedSize > oldSize);
@@ -1827,7 +1827,7 @@ var ASM_CONSTS = {
// Loop through potential heap size increases. If we attempt a too eager reservation that fails, cut down on the
// attempted size and reserve a smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
- for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
+ for(var cutDown = 1; cutDown <= 4; cutDown *= 2) {
var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth
// but limit overreserving (default to capping at +96MB overgrowth at most)
overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 );
@@ -1845,7 +1845,7 @@ var ASM_CONSTS = {
}
var JSEvents={inEventHandler:0,removeAllEventListeners:function() {
- for (var i = JSEvents.eventHandlers.length-1; i >= 0; --i) {
+ for(var i = JSEvents.eventHandlers.length-1; i >= 0; --i) {
JSEvents._removeHandler(i);
}
JSEvents.eventHandlers = [];
@@ -1859,13 +1859,13 @@ var ASM_CONSTS = {
function arraysHaveEqualContent(arrA, arrB) {
if (arrA.length != arrB.length) return false;
- for (var i in arrA) {
+ for(var i in arrA) {
if (arrA[i] != arrB[i]) return false;
}
return true;
}
// Test if the given call was already queued, and if so, don't add it again.
- for (var i in JSEvents.deferredCalls) {
+ for(var i in JSEvents.deferredCalls) {
var call = JSEvents.deferredCalls[i];
if (call.targetFunction == targetFunction && arraysHaveEqualContent(call.argsList, argsList)) {
return;
@@ -1879,7 +1879,7 @@ var ASM_CONSTS = {
JSEvents.deferredCalls.sort(function(x,y) { return x.precedence < y.precedence; });
},removeDeferredCalls:function(targetFunction) {
- for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
+ for(var i = 0; i < JSEvents.deferredCalls.length; ++i) {
if (JSEvents.deferredCalls[i].targetFunction == targetFunction) {
JSEvents.deferredCalls.splice(i, 1);
--i;
@@ -1891,14 +1891,14 @@ var ASM_CONSTS = {
if (!JSEvents.canPerformEventHandlerRequests()) {
return;
}
- for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
+ for(var i = 0; i < JSEvents.deferredCalls.length; ++i) {
var call = JSEvents.deferredCalls[i];
JSEvents.deferredCalls.splice(i, 1);
--i;
call.targetFunction.apply(null, call.argsList);
}
},eventHandlers:[],removeAllHandlersOnTarget:function(target, eventTypeString) {
- for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
+ for(var i = 0; i < JSEvents.eventHandlers.length; ++i) {
if (JSEvents.eventHandlers[i].target == target &&
(!eventTypeString || eventTypeString == JSEvents.eventHandlers[i].eventTypeString)) {
JSEvents._removeHandler(i--);
@@ -1929,7 +1929,7 @@ var ASM_CONSTS = {
JSEvents.eventHandlers.push(eventHandler);
JSEvents.registerRemoveEventListeners();
} else {
- for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
+ for(var i = 0; i < JSEvents.eventHandlers.length; ++i) {
if (JSEvents.eventHandlers[i].target == eventHandler.target
&& JSEvents.eventHandlers[i].eventTypeString == eventHandler.eventTypeString) {
JSEvents._removeHandler(i--);
@@ -2074,7 +2074,7 @@ var ASM_CONSTS = {
// Closure is expected to be allowed to minify the '.multiDrawWebgl' property, so not accessing it quoted.
return !!(ctx.multiDrawWebgl = ctx.getExtension('WEBGL_multi_draw'));
}
- var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode) {
+ var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},timerQueriesEXT:[],queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],programInfos:{},stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode) {
if (!GL.lastError) {
GL.lastError = errorCode;
}
@@ -2085,7 +2085,7 @@ var ASM_CONSTS = {
}
return ret;
},MAX_TEMP_BUFFER_SIZE:2097152,numTempVertexBuffersPerSize:64,log2ceilLookup:function(i) {
- return 32 - Math.clz32(i === 0 ? 0 : i - 1);
+ return 32 - Math.clz32(i-1);
},generateTempBuffers:function(quads, context) {
var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
context.tempVertexBufferCounters1 = [];
@@ -2213,19 +2213,6 @@ var ASM_CONSTS = {
}
},createContext:function(canvas, webGLContextAttributes) {
- // BUG: Workaround Safari WebGL issue: After successfully acquiring WebGL context on a canvas,
- // calling .getContext() will always return that context independent of which 'webgl' or 'webgl2'
- // context version was passed. See https://bugs.webkit.org/show_bug.cgi?id=222758 and
- // https://github.com/emscripten-core/emscripten/issues/13295.
- // TODO: Once the bug is fixed and shipped in Safari, adjust the Safari version field in above check.
- if (!canvas.getContextSafariWebGL2Fixed) {
- canvas.getContextSafariWebGL2Fixed = canvas.getContext;
- canvas.getContext = function(ver, attrs) {
- var gl = canvas.getContextSafariWebGL2Fixed(ver, attrs);
- return ((ver == 'webgl') == (gl instanceof WebGLRenderingContext)) ? gl : null;
- }
- }
-
var ctx =
(webGLContextAttributes.majorVersion > 1)
?
@@ -2298,21 +2285,7 @@ var ASM_CONSTS = {
__webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);
__webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);
- // On WebGL 2, EXT_disjoint_timer_query is replaced with an alternative
- // that's based on core APIs, and exposes only the queryCounterEXT()
- // entrypoint.
- if (context.version >= 2) {
- GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query_webgl2");
- }
-
- // However, Firefox exposes the WebGL 1 version on WebGL 2 as well and
- // thus we look for the WebGL 1 version again if the WebGL 2 version
- // isn't present. https://bugzilla.mozilla.org/show_bug.cgi?id=1328882
- if (context.version < 2 || !GLctx.disjointTimerQueryExt)
- {
- GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
- }
-
+ GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
__webgl_enable_WEBGL_multi_draw(GLctx);
// .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
@@ -2324,6 +2297,49 @@ var ASM_CONSTS = {
GLctx.getExtension(ext);
}
});
+ },populateUniformTable:function(program) {
+ var p = GL.programs[program];
+ var ptable = GL.programInfos[program] = {
+ uniforms: {},
+ maxUniformLength: 0, // This is eagerly computed below, since we already enumerate all uniforms anyway.
+ maxAttributeLength: -1, // This is lazily computed and cached, computed when/if first asked, "-1" meaning not computed yet.
+ maxUniformBlockNameLength: -1 // Lazily computed as well
+ };
+
+ var utable = ptable.uniforms;
+ // A program's uniform table maps the string name of an uniform to an integer location of that uniform.
+ // The global GL.uniforms map maps integer locations to WebGLUniformLocations.
+ var numUniforms = GLctx.getProgramParameter(p, 0x8B86/*GL_ACTIVE_UNIFORMS*/);
+ for (var i = 0; i < numUniforms; ++i) {
+ var u = GLctx.getActiveUniform(p, i);
+
+ var name = u.name;
+ ptable.maxUniformLength = Math.max(ptable.maxUniformLength, name.length+1);
+
+ // If we are dealing with an array, e.g. vec4 foo[3], strip off the array index part to canonicalize that "foo", "foo[]",
+ // and "foo[0]" will mean the same. Loop below will populate foo[1] and foo[2].
+ if (name.slice(-1) == ']') {
+ name = name.slice(0, name.lastIndexOf('['));
+ }
+
+ // Optimize memory usage slightly: If we have an array of uniforms, e.g. 'vec3 colors[3];', then
+ // only store the string 'colors' in utable, and 'colors[0]', 'colors[1]' and 'colors[2]' will be parsed as 'colors'+i.
+ // Note that for the GL.uniforms table, we still need to fetch the all WebGLUniformLocations for all the indices.
+ var loc = GLctx.getUniformLocation(p, name);
+ if (loc) {
+ var id = GL.getNewId(GL.uniforms);
+ utable[name] = [u.size, id];
+ GL.uniforms[id] = loc;
+
+ for (var j = 1; j < u.size; ++j) {
+ var n = name + '['+j+']';
+ loc = GLctx.getUniformLocation(p, n);
+ id = GL.getNewId(GL.uniforms);
+
+ GL.uniforms[id] = loc;
+ }
+ }
+ }
}};
var __emscripten_webgl_power_preferences=['default', 'low-power', 'high-performance'];
@@ -2370,7 +2386,7 @@ var ASM_CONSTS = {
function _emscripten_webgl_init_context_attributes(attributes) {
assert(attributes);
var a = attributes >> 2;
- for (var i = 0; i < (56>>2); ++i) {
+ for(var i = 0; i < (56>>2); ++i) {
HEAP32[a+i] = 0;
}
@@ -2434,7 +2450,8 @@ var ASM_CONSTS = {
}
function _glAttachShader(program, shader) {
- GLctx.attachShader(GL.programs[program], GL.shaders[shader]);
+ GLctx.attachShader(GL.programs[program],
+ GL.shaders[shader]);
}
function _glBindBuffer(target, buffer) {
@@ -2494,11 +2511,7 @@ var ASM_CONSTS = {
function _glCreateProgram() {
var id = GL.getNewId(GL.programs);
var program = GLctx.createProgram();
- // Store additional information needed for each shader program:
program.name = id;
- // Lazy cache results of glGetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH/GL_ACTIVE_ATTRIBUTE_MAX_LENGTH/GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH)
- program.maxUniformLength = program.maxAttributeLength = program.maxUniformBlockNameLength = 0;
- program.uniformIdCounter = 1;
GL.programs[id] = program;
return id;
}
@@ -2506,7 +2519,6 @@ var ASM_CONSTS = {
function _glCreateShader(shaderType) {
var id = GL.getNewId(GL.shaders);
GL.shaders[id] = GLctx.createShader(shaderType);
-
return id;
}
@@ -2540,6 +2552,7 @@ var ASM_CONSTS = {
GLctx.deleteProgram(program);
program.name = 0;
GL.programs[id] = null;
+ GL.programInfos[id] = null;
}
function _glDeleteShader(id) {
@@ -2632,35 +2645,42 @@ var ASM_CONSTS = {
return;
}
- program = GL.programs[program];
+ var ptable = GL.programInfos[program];
+ if (!ptable) {
+ GL.recordError(0x502 /* GL_INVALID_OPERATION */);
+ return;
+ }
if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
- var log = GLctx.getProgramInfoLog(program);
+ var log = GLctx.getProgramInfoLog(GL.programs[program]);
if (log === null) log = '(unknown error)';
HEAP32[((p)>>2)] = log.length + 1;
} else if (pname == 0x8B87 /* GL_ACTIVE_UNIFORM_MAX_LENGTH */) {
- if (!program.maxUniformLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8B86/*GL_ACTIVE_UNIFORMS*/); ++i) {
- program.maxUniformLength = Math.max(program.maxUniformLength, GLctx.getActiveUniform(program, i).name.length+1);
- }
- }
- HEAP32[((p)>>2)] = program.maxUniformLength;
+ HEAP32[((p)>>2)] = ptable.maxUniformLength;
} else if (pname == 0x8B8A /* GL_ACTIVE_ATTRIBUTE_MAX_LENGTH */) {
- if (!program.maxAttributeLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/); ++i) {
- program.maxAttributeLength = Math.max(program.maxAttributeLength, GLctx.getActiveAttrib(program, i).name.length+1);
+ if (ptable.maxAttributeLength == -1) {
+ program = GL.programs[program];
+ var numAttribs = GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/);
+ ptable.maxAttributeLength = 0; // Spec says if there are no active attribs, 0 must be returned.
+ for (var i = 0; i < numAttribs; ++i) {
+ var activeAttrib = GLctx.getActiveAttrib(program, i);
+ ptable.maxAttributeLength = Math.max(ptable.maxAttributeLength, activeAttrib.name.length+1);
}
}
- HEAP32[((p)>>2)] = program.maxAttributeLength;
+ HEAP32[((p)>>2)] = ptable.maxAttributeLength;
} else if (pname == 0x8A35 /* GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH */) {
- if (!program.maxUniformBlockNameLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/); ++i) {
- program.maxUniformBlockNameLength = Math.max(program.maxUniformBlockNameLength, GLctx.getActiveUniformBlockName(program, i).length+1);
+ if (ptable.maxUniformBlockNameLength == -1) {
+ program = GL.programs[program];
+ var numBlocks = GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/);
+ ptable.maxUniformBlockNameLength = 0;
+ for (var i = 0; i < numBlocks; ++i) {
+ var activeBlockName = GLctx.getActiveUniformBlockName(program, i);
+ ptable.maxUniformBlockNameLength = Math.max(ptable.maxUniformBlockNameLength, activeBlockName.length+1);
}
}
- HEAP32[((p)>>2)] = program.maxUniformBlockNameLength;
+ HEAP32[((p)>>2)] = ptable.maxUniformBlockNameLength;
} else {
- HEAP32[((p)>>2)] = GLctx.getProgramParameter(program, pname);
+ HEAP32[((p)>>2)] = GLctx.getProgramParameter(GL.programs[program], pname);
}
}
@@ -2703,91 +2723,27 @@ var ASM_CONSTS = {
return parseInt(str);
}
function _glGetUniformLocation(program, name) {
- // Returns the index of '[' character in an uniform that represents an array of uniforms (e.g. colors[10])
- // Closure does counterproductive inlining: https://github.com/google/closure-compiler/issues/3203, so prevent
- // inlining manually.
- /** @noinline */
- function getLeftBracePos(name) {
- return name.slice(-1) == ']' && name.lastIndexOf('[');
- }
-
name = UTF8ToString(name);
- program = GL.programs[program];
- var uniformLocsById = program.uniformLocsById; // Maps GLuint -> WebGLUniformLocation
- var uniformSizeAndIdsByName = program.uniformSizeAndIdsByName; // Maps name -> [uniform array length, GLuint]
- var i, j;
var arrayIndex = 0;
- var uniformBaseName = name;
-
- // Invariant: when populating integer IDs for uniform locations, we must maintain the precondition that
- // arrays reside in contiguous addresses, i.e. for a 'vec4 colors[10];', colors[4] must be at location colors[0]+4.
- // However, user might call glGetUniformLocation(program, "colors") for an array, so we cannot discover based on the user
- // input arguments whether the uniform we are dealing with is an array. The only way to discover which uniforms are arrays
- // is to enumerate over all the active uniforms in the program.
- var leftBrace = getLeftBracePos(name);
-
- // On the first time invocation of glGetUniformLocation on this shader program:
- // initialize cache data structures and discover which uniforms are arrays.
- if (!uniformLocsById) {
- // maps GLint integer locations to WebGLUniformLocations
- program.uniformLocsById = uniformLocsById = {};
- // maps integer locations back to uniform name strings, so that we can lazily fetch uniform array locations
- program.uniformArrayNamesById = {};
-
- for (i = 0; i < GLctx.getProgramParameter(program, 0x8B86/*GL_ACTIVE_UNIFORMS*/); ++i) {
- var u = GLctx.getActiveUniform(program, i);
- var nm = u.name;
- var sz = u.size;
- var lb = getLeftBracePos(nm);
- var arrayName = lb > 0 ? nm.slice(0, lb) : nm;
-
- // Assign a new location.
- var id = program.uniformIdCounter;
- program.uniformIdCounter += sz;
- // Eagerly get the location of the uniformArray[0] base element.
- // The remaining indices >0 will be left for lazy evaluation to
- // improve performance. Those may never be needed to fetch, if the
- // application fills arrays always in full starting from the first
- // element of the array.
- uniformSizeAndIdsByName[arrayName] = [sz, id];
-
- // Store placeholder integers in place that highlight that these
- // >0 index locations are array indices pending population.
- for(j = 0; j < sz; ++j) {
- uniformLocsById[id] = j;
- program.uniformArrayNamesById[id++] = arrayName;
- }
- }
- }
-
// If user passed an array accessor "[index]", parse the array index off the accessor.
- if (leftBrace > 0) {
- arrayIndex = jstoi_q(name.slice(leftBrace + 1)) >>> 0; // "index]", coerce parseInt(']') with >>>0 to treat "foo[]" as "foo[0]" and foo[-1] as unsigned out-of-bounds.
- uniformBaseName = name.slice(0, leftBrace);
+ if (name[name.length - 1] == ']') {
+ var leftBrace = name.lastIndexOf('[');
+ arrayIndex = name[leftBrace+1] != ']' ? jstoi_q(name.slice(leftBrace + 1)) : 0; // "index]", parseInt will ignore the ']' at the end; but treat "foo[]" as "foo[0]"
+ name = name.slice(0, leftBrace);
}
- // Have we cached the location of this uniform before?
- var sizeAndId = uniformSizeAndIdsByName[uniformBaseName]; // A pair [array length, GLint of the uniform location]
-
- // If an uniform with this name exists, and if its index is within the array limits (if it's even an array),
- // query the WebGLlocation, or return an existing cached location.
- if (sizeAndId && arrayIndex < sizeAndId[0]) {
- arrayIndex += sizeAndId[1]; // Add the base location of the uniform to the array index offset.
- if ((uniformLocsById[arrayIndex] = uniformLocsById[arrayIndex] || GLctx.getUniformLocation(program, name))) {
- return arrayIndex;
- }
+ var uniformInfo = GL.programInfos[program] && GL.programInfos[program].uniforms[name]; // returns pair [ dimension_of_uniform_array, uniform_location ]
+ if (uniformInfo && arrayIndex >= 0 && arrayIndex < uniformInfo[0]) { // Check if user asked for an out-of-bounds element, i.e. for 'vec4 colors[3];' user could ask for 'colors[10]' which should return -1.
+ return uniformInfo[1] + arrayIndex;
+ } else {
+ return -1;
}
- return -1;
}
function _glLinkProgram(program) {
- program = GL.programs[program];
- GLctx.linkProgram(program);
- // Invalidate earlier computed uniform->ID mappings, those have now become stale
- program.uniformLocsById = 0; // Mark as null-like so that glGetUniformLocation() knows to populate this again.
- program.uniformSizeAndIdsByName = {};
-
+ GLctx.linkProgram(GL.programs[program]);
+ GL.populateUniformTable(program);
}
function _glShaderSource(shader, count, string, length) {
@@ -2796,25 +2752,11 @@ var ASM_CONSTS = {
GLctx.shaderSource(GL.shaders[shader], source);
}
- function webglGetUniformLocation(location) {
- var p = GLctx.currentProgram;
- var webglLoc = p.uniformLocsById[location];
- // p.uniformLocsById[location] stores either an integer, or a WebGLUniformLocation.
-
- // If an integer, we have not yet bound the location, so do it now. The integer value specifies the array index
- // we should bind to.
- if (webglLoc >= 0) {
- p.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(p, p.uniformArrayNamesById[location] + (webglLoc > 0 ? '[' + webglLoc + ']' : ''));
- }
- // Else an already cached WebGLUniformLocation, return it.
- return webglLoc;
- }
-
var miniTempWebGLFloatBuffers=[];
function _glUniformMatrix4fv(location, count, transpose, value) {
if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible.
- GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*16);
+ GLctx.uniformMatrix4fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*16);
return;
}
@@ -2847,15 +2789,11 @@ var ASM_CONSTS = {
{
var view = HEAPF32.subarray((value)>>2, (value+count*64)>>2);
}
- GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, view);
+ GLctx.uniformMatrix4fv(GL.uniforms[location], !!transpose, view);
}
function _glUseProgram(program) {
- program = GL.programs[program];
- GLctx.useProgram(program);
- // Record the currently active program so that we can access the uniform
- // mapping table of that program.
- GLctx.currentProgram = program;
+ GLctx.useProgram(GL.programs[program]);
}
function _glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
@@ -3066,10 +3004,6 @@ if (!Object.getOwnPropertyDescriptor(Module, "ENV")) Module["ENV"] = function()
if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_CODES")) Module["ERRNO_CODES"] = function() { abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_MESSAGES")) Module["ERRNO_MESSAGES"] = function() { abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "setErrNo")) Module["setErrNo"] = function() { abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetPton4")) Module["inetPton4"] = function() { abort("'inetPton4' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetNtop4")) Module["inetNtop4"] = function() { abort("'inetNtop4' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetPton6")) Module["inetPton6"] = function() { abort("'inetPton6' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetNtop6")) Module["inetNtop6"] = function() { abort("'inetNtop6' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "readSockaddr")) Module["readSockaddr"] = function() { abort("'readSockaddr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "writeSockaddr")) Module["writeSockaddr"] = function() { abort("'writeSockaddr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "DNS")) Module["DNS"] = function() { abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
@@ -3093,12 +3027,7 @@ if (!Object.getOwnPropertyDescriptor(Module, "dynCallLegacy")) Module["dynCallLe
if (!Object.getOwnPropertyDescriptor(Module, "getDynCaller")) Module["getDynCaller"] = function() { abort("'getDynCaller' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "dynCall")) Module["dynCall"] = function() { abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "callRuntimeCallbacks")) Module["callRuntimeCallbacks"] = function() { abort("'callRuntimeCallbacks' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "runtimeKeepaliveCounter")) Module["runtimeKeepaliveCounter"] = function() { abort("'runtimeKeepaliveCounter' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "keepRuntimeAlive")) Module["keepRuntimeAlive"] = function() { abort("'keepRuntimeAlive' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "runtimeKeepalivePush")) Module["runtimeKeepalivePush"] = function() { abort("'runtimeKeepalivePush' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "runtimeKeepalivePop")) Module["runtimeKeepalivePop"] = function() { abort("'runtimeKeepalivePop' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "callUserCallback")) Module["callUserCallback"] = function() { abort("'callUserCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "maybeExit")) Module["maybeExit"] = function() { abort("'maybeExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Object.getOwnPropertyDescriptor(Module, "abortStackOverflow")) Module["abortStackOverflow"] = function() { abort("'abortStackOverflow' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "reallyNegative")) Module["reallyNegative"] = function() { abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "unSign")) Module["unSign"] = function() { abort("'unSign' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "reSign")) Module["reSign"] = function() { abort("'reSign' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
@@ -3199,7 +3128,6 @@ if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGet")) Module["emsc
if (!Object.getOwnPropertyDescriptor(Module, "computeUnpackAlignedImageSize")) Module["computeUnpackAlignedImageSize"] = function() { abort("'computeUnpackAlignedImageSize' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetTexPixelData")) Module["emscriptenWebGLGetTexPixelData"] = function() { abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetUniform")) Module["emscriptenWebGLGetUniform"] = function() { abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "webglGetUniformLocation")) Module["webglGetUniformLocation"] = function() { abort("'webglGetUniformLocation' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetVertexAttrib")) Module["emscriptenWebGLGetVertexAttrib"] = function() { abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetBufferBinding")) Module["emscriptenWebGLGetBufferBinding"] = function() { abort("'emscriptenWebGLGetBufferBinding' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLValidateMapBufferTarget")) Module["emscriptenWebGLValidateMapBufferTarget"] = function() { abort("'emscriptenWebGLValidateMapBufferTarget' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
@@ -3289,6 +3217,7 @@ function callMain(args) {
return;
} else if (e == 'unwind') {
// running an evented main loop, don't immediately exit
+ noExitRuntime = true;
return;
} else {
var toLog = e;
@@ -3398,19 +3327,17 @@ function checkUnflushedContent() {
/** @param {boolean|number=} implicit */
function exit(status, implicit) {
- EXITSTATUS = status;
-
checkUnflushedContent();
// if this is just main exit-ing implicitly, and the status is 0, then we
// don't need to do anything here and can just leave. if the status is
// non-zero, though, then we need to report it.
// (we may have warned about this earlier, if a situation justifies doing so)
- if (implicit && keepRuntimeAlive() && status === 0) {
+ if (implicit && noExitRuntime && status === 0) {
return;
}
- if (keepRuntimeAlive()) {
+ if (noExitRuntime) {
// if exit() was called, we may warn the user if the runtime isn't actually being shut down
if (!implicit) {
var msg = 'program exited (with status: ' + status + '), but EXIT_RUNTIME is not set, so halting execution but not exiting the runtime or preventing further async execution (build with EXIT_RUNTIME=1, if you want a true shutdown)';
@@ -3418,6 +3345,8 @@ function exit(status, implicit) {
}
} else {
+ EXITSTATUS = status;
+
exitRuntime();
if (Module['onExit']) Module['onExit'](status);
diff --git a/2d/_collisions/rectangle_rectangle/dist/output.wasm b/2d/_collisions/rectangle_rectangle/dist/output.wasm
index f61e371..8e81cb7 100755
Binary files a/2d/_collisions/rectangle_rectangle/dist/output.wasm and b/2d/_collisions/rectangle_rectangle/dist/output.wasm differ
diff --git a/2d/_collisions/rectangle_rectangle/main.cpp b/2d/_collisions/rectangle_rectangle/main.cpp
index 689ea11..6913749 100644
--- a/2d/_collisions/rectangle_rectangle/main.cpp
+++ b/2d/_collisions/rectangle_rectangle/main.cpp
@@ -411,12 +411,12 @@ void update(float32 deltaTimeSeconds, void* userData) {
rect->body.position.y = 0.f;
rect->body.velocity = rect->body.velocity - Vector2 { 0.f, 1.f } * (2 * (rect->body.velocity.dot(Vector2 { 0.f, 1.f })));
}
- if (rect->body.position.x >= 640.f) {
- rect->body.position.x = 640.f;
+ if (rect->body.position.x >= 800.f) {
+ rect->body.position.x = 800.f;
rect->body.velocity = rect->body.velocity - Vector2 { -1.f, 0.f } * (2 * (rect->body.velocity.dot(Vector2{ -1.f, 0.f })));
}
- if (rect->body.position.y >= 480.f) {
- rect->body.position.y = 480.f;
+ if (rect->body.position.y >= 600.f) {
+ rect->body.position.y = 600.f;
rect->body.velocity = rect->body.velocity - Vector2 { 0.f, -1.f } * (2 * (rect->body.velocity.dot(Vector2 { 0.f, -1.f }))) ;
}
}
diff --git a/2d/rigidbody/rigidbody_1.html b/2d/rigidbody/rigidbody_1.html
index 8fdcd07..83cc237 100644
--- a/2d/rigidbody/rigidbody_1.html
+++ b/2d/rigidbody/rigidbody_1.html
@@ -18,14 +18,14 @@
🏀2D
-
+
diff --git a/2d/rigidbody/rigidbody_1/dist/output.js b/2d/rigidbody/rigidbody_1/dist/output.js
index 42a4ed5..9ba383a 100644
--- a/2d/rigidbody/rigidbody_1/dist/output.js
+++ b/2d/rigidbody/rigidbody_1/dist/output.js
@@ -609,7 +609,7 @@ if (typeof WebAssembly !== 'object') {
function setValue(ptr, value, type, noSafe) {
type = type || 'i8';
if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
- switch (type) {
+ switch(type) {
case 'i1': HEAP8[((ptr)>>0)] = value; break;
case 'i8': HEAP8[((ptr)>>0)] = value; break;
case 'i16': HEAP16[((ptr)>>1)] = value; break;
@@ -627,7 +627,7 @@ function setValue(ptr, value, type, noSafe) {
function getValue(ptr, type, noSafe) {
type = type || 'i8';
if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
- switch (type) {
+ switch(type) {
case 'i1': return HEAP8[((ptr)>>0)];
case 'i8': return HEAP8[((ptr)>>0)];
case 'i16': return HEAP16[((ptr)>>1)];
@@ -808,7 +808,7 @@ function UTF8ArrayToString(heap, idx, maxBytesToRead) {
if ((u0 & 0xF0) == 0xE0) {
u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
} else {
- if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
+ if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!');
u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heap[idx++] & 63);
}
@@ -884,7 +884,7 @@ function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
heap[outIdx++] = 0x80 | (u & 63);
} else {
if (outIdx + 3 >= endIdx) break;
- if (u >= 0x200000) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x1FFFFF).');
+ if (u >= 0x200000) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).');
heap[outIdx++] = 0xF0 | (u >> 18);
heap[outIdx++] = 0x80 | ((u >> 12) & 63);
heap[outIdx++] = 0x80 | ((u >> 6) & 63);
@@ -1252,12 +1252,12 @@ function checkStackCookie() {
// include: runtime_assertions.js
-// Endianness check
+// Endianness check (note: assumes compiler arch was little-endian)
(function() {
var h16 = new Int16Array(1);
var h8 = new Int8Array(h16.buffer);
h16[0] = 0x6373;
- if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -s SUPPORT_BIG_ENDIAN=1 to bypass)';
+ if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian!';
})();
function abortFnPtrError(ptr, sig) {
@@ -1274,6 +1274,8 @@ var __ATPOSTRUN__ = []; // functions called after the main() is called
var runtimeInitialized = false;
var runtimeExited = false;
+__ATINIT__.push({ func: function() { ___wasm_call_ctors() } });
+
function preRun() {
if (Module['preRun']) {
@@ -1290,7 +1292,6 @@ function initRuntime() {
checkStackCookie();
assert(!runtimeInitialized);
runtimeInitialized = true;
-
callRuntimeCallbacks(__ATINIT__);
}
@@ -1615,8 +1616,6 @@ function createWasm() {
wasmTable = Module['asm']['__indirect_function_table'];
assert(wasmTable, "table not found in wasm exports");
- addOnInit(Module['asm']['__wasm_call_ctors']);
-
removeRunDependency('wasm-instantiate');
}
// we can't run yet (except in a pthread, where we have a custom sync instantiator)
@@ -1638,8 +1637,7 @@ function createWasm() {
function instantiateArrayBuffer(receiver) {
return getBinaryPromise().then(function(binary) {
- var result = WebAssembly.instantiate(binary, info);
- return result;
+ return WebAssembly.instantiate(binary, info);
}).then(receiver, function(reason) {
err('failed to asynchronously prepare wasm: ' + reason);
@@ -1706,8 +1704,12 @@ var ASM_CONSTS = {
+ function abortStackOverflow(allocSize) {
+ abort('Stack overflow! Attempted to allocate ' + allocSize + ' bytes on the stack, but stack has only ' + (_emscripten_stack_get_free() + allocSize) + ' bytes available!');
+ }
+
function callRuntimeCallbacks(callbacks) {
- while (callbacks.length > 0) {
+ while(callbacks.length > 0) {
var callback = callbacks.shift();
if (typeof callback == 'function') {
callback(Module); // Pass the module as the first argument.
@@ -1758,11 +1760,6 @@ var ASM_CONSTS = {
return error.stack.toString();
}
- var runtimeKeepaliveCounter=0;
- function keepRuntimeAlive() {
- return noExitRuntime || runtimeKeepaliveCounter > 0;
- }
-
function stackTrace() {
var js = jsStackTrace();
if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace']();
@@ -1786,6 +1783,10 @@ var ASM_CONSTS = {
return requestAnimationFrame(tick);
}
+ function _emscripten_get_heap_size() {
+ return HEAPU8.length;
+ }
+
function emscripten_realloc_buffer(size) {
try {
// round size grow request up to wasm page size (fixed 64KB per spec)
@@ -1799,8 +1800,7 @@ var ASM_CONSTS = {
// anyhow)
}
function _emscripten_resize_heap(requestedSize) {
- var oldSize = HEAPU8.length;
- requestedSize = requestedSize >>> 0;
+ var oldSize = _emscripten_get_heap_size();
// With pthreads, races can happen (another thread might increase the size in between), so return a failure, and let the caller retry.
assert(requestedSize > oldSize);
@@ -1827,7 +1827,7 @@ var ASM_CONSTS = {
// Loop through potential heap size increases. If we attempt a too eager reservation that fails, cut down on the
// attempted size and reserve a smaller bump instead. (max 3 times, chosen somewhat arbitrarily)
- for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
+ for(var cutDown = 1; cutDown <= 4; cutDown *= 2) {
var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); // ensure geometric growth
// but limit overreserving (default to capping at +96MB overgrowth at most)
overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296 );
@@ -1845,7 +1845,7 @@ var ASM_CONSTS = {
}
var JSEvents={inEventHandler:0,removeAllEventListeners:function() {
- for (var i = JSEvents.eventHandlers.length-1; i >= 0; --i) {
+ for(var i = JSEvents.eventHandlers.length-1; i >= 0; --i) {
JSEvents._removeHandler(i);
}
JSEvents.eventHandlers = [];
@@ -1859,13 +1859,13 @@ var ASM_CONSTS = {
function arraysHaveEqualContent(arrA, arrB) {
if (arrA.length != arrB.length) return false;
- for (var i in arrA) {
+ for(var i in arrA) {
if (arrA[i] != arrB[i]) return false;
}
return true;
}
// Test if the given call was already queued, and if so, don't add it again.
- for (var i in JSEvents.deferredCalls) {
+ for(var i in JSEvents.deferredCalls) {
var call = JSEvents.deferredCalls[i];
if (call.targetFunction == targetFunction && arraysHaveEqualContent(call.argsList, argsList)) {
return;
@@ -1879,7 +1879,7 @@ var ASM_CONSTS = {
JSEvents.deferredCalls.sort(function(x,y) { return x.precedence < y.precedence; });
},removeDeferredCalls:function(targetFunction) {
- for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
+ for(var i = 0; i < JSEvents.deferredCalls.length; ++i) {
if (JSEvents.deferredCalls[i].targetFunction == targetFunction) {
JSEvents.deferredCalls.splice(i, 1);
--i;
@@ -1891,14 +1891,14 @@ var ASM_CONSTS = {
if (!JSEvents.canPerformEventHandlerRequests()) {
return;
}
- for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
+ for(var i = 0; i < JSEvents.deferredCalls.length; ++i) {
var call = JSEvents.deferredCalls[i];
JSEvents.deferredCalls.splice(i, 1);
--i;
call.targetFunction.apply(null, call.argsList);
}
},eventHandlers:[],removeAllHandlersOnTarget:function(target, eventTypeString) {
- for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
+ for(var i = 0; i < JSEvents.eventHandlers.length; ++i) {
if (JSEvents.eventHandlers[i].target == target &&
(!eventTypeString || eventTypeString == JSEvents.eventHandlers[i].eventTypeString)) {
JSEvents._removeHandler(i--);
@@ -1929,7 +1929,7 @@ var ASM_CONSTS = {
JSEvents.eventHandlers.push(eventHandler);
JSEvents.registerRemoveEventListeners();
} else {
- for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
+ for(var i = 0; i < JSEvents.eventHandlers.length; ++i) {
if (JSEvents.eventHandlers[i].target == eventHandler.target
&& JSEvents.eventHandlers[i].eventTypeString == eventHandler.eventTypeString) {
JSEvents._removeHandler(i--);
@@ -2028,6 +2028,11 @@ var ASM_CONSTS = {
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 __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');
@@ -2074,7 +2079,7 @@ var ASM_CONSTS = {
// Closure is expected to be allowed to minify the '.multiDrawWebgl' property, so not accessing it quoted.
return !!(ctx.multiDrawWebgl = ctx.getExtension('WEBGL_multi_draw'));
}
- var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode) {
+ var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},timerQueriesEXT:[],queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],programInfos:{},stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode) {
if (!GL.lastError) {
GL.lastError = errorCode;
}
@@ -2085,7 +2090,7 @@ var ASM_CONSTS = {
}
return ret;
},MAX_TEMP_BUFFER_SIZE:2097152,numTempVertexBuffersPerSize:64,log2ceilLookup:function(i) {
- return 32 - Math.clz32(i === 0 ? 0 : i - 1);
+ return 32 - Math.clz32(i-1);
},generateTempBuffers:function(quads, context) {
var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
context.tempVertexBufferCounters1 = [];
@@ -2213,19 +2218,6 @@ var ASM_CONSTS = {
}
},createContext:function(canvas, webGLContextAttributes) {
- // BUG: Workaround Safari WebGL issue: After successfully acquiring WebGL context on a canvas,
- // calling .getContext() will always return that context independent of which 'webgl' or 'webgl2'
- // context version was passed. See https://bugs.webkit.org/show_bug.cgi?id=222758 and
- // https://github.com/emscripten-core/emscripten/issues/13295.
- // TODO: Once the bug is fixed and shipped in Safari, adjust the Safari version field in above check.
- if (!canvas.getContextSafariWebGL2Fixed) {
- canvas.getContextSafariWebGL2Fixed = canvas.getContext;
- canvas.getContext = function(ver, attrs) {
- var gl = canvas.getContextSafariWebGL2Fixed(ver, attrs);
- return ((ver == 'webgl') == (gl instanceof WebGLRenderingContext)) ? gl : null;
- }
- }
-
var ctx =
(webGLContextAttributes.majorVersion > 1)
?
@@ -2298,21 +2290,7 @@ var ASM_CONSTS = {
__webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);
__webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);
- // On WebGL 2, EXT_disjoint_timer_query is replaced with an alternative
- // that's based on core APIs, and exposes only the queryCounterEXT()
- // entrypoint.
- if (context.version >= 2) {
- GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query_webgl2");
- }
-
- // However, Firefox exposes the WebGL 1 version on WebGL 2 as well and
- // thus we look for the WebGL 1 version again if the WebGL 2 version
- // isn't present. https://bugzilla.mozilla.org/show_bug.cgi?id=1328882
- if (context.version < 2 || !GLctx.disjointTimerQueryExt)
- {
- GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
- }
-
+ GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
__webgl_enable_WEBGL_multi_draw(GLctx);
// .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
@@ -2324,6 +2302,49 @@ var ASM_CONSTS = {
GLctx.getExtension(ext);
}
});
+ },populateUniformTable:function(program) {
+ var p = GL.programs[program];
+ var ptable = GL.programInfos[program] = {
+ uniforms: {},
+ maxUniformLength: 0, // This is eagerly computed below, since we already enumerate all uniforms anyway.
+ maxAttributeLength: -1, // This is lazily computed and cached, computed when/if first asked, "-1" meaning not computed yet.
+ maxUniformBlockNameLength: -1 // Lazily computed as well
+ };
+
+ var utable = ptable.uniforms;
+ // A program's uniform table maps the string name of an uniform to an integer location of that uniform.
+ // The global GL.uniforms map maps integer locations to WebGLUniformLocations.
+ var numUniforms = GLctx.getProgramParameter(p, 0x8B86/*GL_ACTIVE_UNIFORMS*/);
+ for (var i = 0; i < numUniforms; ++i) {
+ var u = GLctx.getActiveUniform(p, i);
+
+ var name = u.name;
+ ptable.maxUniformLength = Math.max(ptable.maxUniformLength, name.length+1);
+
+ // If we are dealing with an array, e.g. vec4 foo[3], strip off the array index part to canonicalize that "foo", "foo[]",
+ // and "foo[0]" will mean the same. Loop below will populate foo[1] and foo[2].
+ if (name.slice(-1) == ']') {
+ name = name.slice(0, name.lastIndexOf('['));
+ }
+
+ // Optimize memory usage slightly: If we have an array of uniforms, e.g. 'vec3 colors[3];', then
+ // only store the string 'colors' in utable, and 'colors[0]', 'colors[1]' and 'colors[2]' will be parsed as 'colors'+i.
+ // Note that for the GL.uniforms table, we still need to fetch the all WebGLUniformLocations for all the indices.
+ var loc = GLctx.getUniformLocation(p, name);
+ if (loc) {
+ var id = GL.getNewId(GL.uniforms);
+ utable[name] = [u.size, id];
+ GL.uniforms[id] = loc;
+
+ for (var j = 1; j < u.size; ++j) {
+ var n = name + '['+j+']';
+ loc = GLctx.getUniformLocation(p, n);
+ id = GL.getNewId(GL.uniforms);
+
+ GL.uniforms[id] = loc;
+ }
+ }
+ }
}};
var __emscripten_webgl_power_preferences=['default', 'low-power', 'high-performance'];
@@ -2370,7 +2391,7 @@ var ASM_CONSTS = {
function _emscripten_webgl_init_context_attributes(attributes) {
assert(attributes);
var a = attributes >> 2;
- for (var i = 0; i < (56>>2); ++i) {
+ for(var i = 0; i < (56>>2); ++i) {
HEAP32[a+i] = 0;
}
@@ -2434,7 +2455,8 @@ var ASM_CONSTS = {
}
function _glAttachShader(program, shader) {
- GLctx.attachShader(GL.programs[program], GL.shaders[shader]);
+ GLctx.attachShader(GL.programs[program],
+ GL.shaders[shader]);
}
function _glBindBuffer(target, buffer) {
@@ -2494,11 +2516,7 @@ var ASM_CONSTS = {
function _glCreateProgram() {
var id = GL.getNewId(GL.programs);
var program = GLctx.createProgram();
- // Store additional information needed for each shader program:
program.name = id;
- // Lazy cache results of glGetProgramiv(GL_ACTIVE_UNIFORM_MAX_LENGTH/GL_ACTIVE_ATTRIBUTE_MAX_LENGTH/GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH)
- program.maxUniformLength = program.maxAttributeLength = program.maxUniformBlockNameLength = 0;
- program.uniformIdCounter = 1;
GL.programs[id] = program;
return id;
}
@@ -2506,7 +2524,6 @@ var ASM_CONSTS = {
function _glCreateShader(shaderType) {
var id = GL.getNewId(GL.shaders);
GL.shaders[id] = GLctx.createShader(shaderType);
-
return id;
}
@@ -2540,6 +2557,7 @@ var ASM_CONSTS = {
GLctx.deleteProgram(program);
program.name = 0;
GL.programs[id] = null;
+ GL.programInfos[id] = null;
}
function _glDeleteShader(id) {
@@ -2632,35 +2650,42 @@ var ASM_CONSTS = {
return;
}
- program = GL.programs[program];
+ var ptable = GL.programInfos[program];
+ if (!ptable) {
+ GL.recordError(0x502 /* GL_INVALID_OPERATION */);
+ return;
+ }
if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
- var log = GLctx.getProgramInfoLog(program);
+ var log = GLctx.getProgramInfoLog(GL.programs[program]);
if (log === null) log = '(unknown error)';
HEAP32[((p)>>2)] = log.length + 1;
} else if (pname == 0x8B87 /* GL_ACTIVE_UNIFORM_MAX_LENGTH */) {
- if (!program.maxUniformLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8B86/*GL_ACTIVE_UNIFORMS*/); ++i) {
- program.maxUniformLength = Math.max(program.maxUniformLength, GLctx.getActiveUniform(program, i).name.length+1);
- }
- }
- HEAP32[((p)>>2)] = program.maxUniformLength;
+ HEAP32[((p)>>2)] = ptable.maxUniformLength;
} else if (pname == 0x8B8A /* GL_ACTIVE_ATTRIBUTE_MAX_LENGTH */) {
- if (!program.maxAttributeLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/); ++i) {
- program.maxAttributeLength = Math.max(program.maxAttributeLength, GLctx.getActiveAttrib(program, i).name.length+1);
+ if (ptable.maxAttributeLength == -1) {
+ program = GL.programs[program];
+ var numAttribs = GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/);
+ ptable.maxAttributeLength = 0; // Spec says if there are no active attribs, 0 must be returned.
+ for (var i = 0; i < numAttribs; ++i) {
+ var activeAttrib = GLctx.getActiveAttrib(program, i);
+ ptable.maxAttributeLength = Math.max(ptable.maxAttributeLength, activeAttrib.name.length+1);
}
}
- HEAP32[((p)>>2)] = program.maxAttributeLength;
+ HEAP32[((p)>>2)] = ptable.maxAttributeLength;
} else if (pname == 0x8A35 /* GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH */) {
- if (!program.maxUniformBlockNameLength) {
- for (var i = 0; i < GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/); ++i) {
- program.maxUniformBlockNameLength = Math.max(program.maxUniformBlockNameLength, GLctx.getActiveUniformBlockName(program, i).length+1);
+ if (ptable.maxUniformBlockNameLength == -1) {
+ program = GL.programs[program];
+ var numBlocks = GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/);
+ ptable.maxUniformBlockNameLength = 0;
+ for (var i = 0; i < numBlocks; ++i) {
+ var activeBlockName = GLctx.getActiveUniformBlockName(program, i);
+ ptable.maxUniformBlockNameLength = Math.max(ptable.maxUniformBlockNameLength, activeBlockName.length+1);
}
}
- HEAP32[((p)>>2)] = program.maxUniformBlockNameLength;
+ HEAP32[((p)>>2)] = ptable.maxUniformBlockNameLength;
} else {
- HEAP32[((p)>>2)] = GLctx.getProgramParameter(program, pname);
+ HEAP32[((p)>>2)] = GLctx.getProgramParameter(GL.programs[program], pname);
}
}
@@ -2703,91 +2728,27 @@ var ASM_CONSTS = {
return parseInt(str);
}
function _glGetUniformLocation(program, name) {
- // Returns the index of '[' character in an uniform that represents an array of uniforms (e.g. colors[10])
- // Closure does counterproductive inlining: https://github.com/google/closure-compiler/issues/3203, so prevent
- // inlining manually.
- /** @noinline */
- function getLeftBracePos(name) {
- return name.slice(-1) == ']' && name.lastIndexOf('[');
- }
-
name = UTF8ToString(name);
- program = GL.programs[program];
- var uniformLocsById = program.uniformLocsById; // Maps GLuint -> WebGLUniformLocation
- var uniformSizeAndIdsByName = program.uniformSizeAndIdsByName; // Maps name -> [uniform array length, GLuint]
- var i, j;
var arrayIndex = 0;
- var uniformBaseName = name;
-
- // Invariant: when populating integer IDs for uniform locations, we must maintain the precondition that
- // arrays reside in contiguous addresses, i.e. for a 'vec4 colors[10];', colors[4] must be at location colors[0]+4.
- // However, user might call glGetUniformLocation(program, "colors") for an array, so we cannot discover based on the user
- // input arguments whether the uniform we are dealing with is an array. The only way to discover which uniforms are arrays
- // is to enumerate over all the active uniforms in the program.
- var leftBrace = getLeftBracePos(name);
-
- // On the first time invocation of glGetUniformLocation on this shader program:
- // initialize cache data structures and discover which uniforms are arrays.
- if (!uniformLocsById) {
- // maps GLint integer locations to WebGLUniformLocations
- program.uniformLocsById = uniformLocsById = {};
- // maps integer locations back to uniform name strings, so that we can lazily fetch uniform array locations
- program.uniformArrayNamesById = {};
-
- for (i = 0; i < GLctx.getProgramParameter(program, 0x8B86/*GL_ACTIVE_UNIFORMS*/); ++i) {
- var u = GLctx.getActiveUniform(program, i);
- var nm = u.name;
- var sz = u.size;
- var lb = getLeftBracePos(nm);
- var arrayName = lb > 0 ? nm.slice(0, lb) : nm;
-
- // Assign a new location.
- var id = program.uniformIdCounter;
- program.uniformIdCounter += sz;
- // Eagerly get the location of the uniformArray[0] base element.
- // The remaining indices >0 will be left for lazy evaluation to
- // improve performance. Those may never be needed to fetch, if the
- // application fills arrays always in full starting from the first
- // element of the array.
- uniformSizeAndIdsByName[arrayName] = [sz, id];
-
- // Store placeholder integers in place that highlight that these
- // >0 index locations are array indices pending population.
- for(j = 0; j < sz; ++j) {
- uniformLocsById[id] = j;
- program.uniformArrayNamesById[id++] = arrayName;
- }
- }
- }
-
// If user passed an array accessor "[index]", parse the array index off the accessor.
- if (leftBrace > 0) {
- arrayIndex = jstoi_q(name.slice(leftBrace + 1)) >>> 0; // "index]", coerce parseInt(']') with >>>0 to treat "foo[]" as "foo[0]" and foo[-1] as unsigned out-of-bounds.
- uniformBaseName = name.slice(0, leftBrace);
+ if (name[name.length - 1] == ']') {
+ var leftBrace = name.lastIndexOf('[');
+ arrayIndex = name[leftBrace+1] != ']' ? jstoi_q(name.slice(leftBrace + 1)) : 0; // "index]", parseInt will ignore the ']' at the end; but treat "foo[]" as "foo[0]"
+ name = name.slice(0, leftBrace);
}
- // Have we cached the location of this uniform before?
- var sizeAndId = uniformSizeAndIdsByName[uniformBaseName]; // A pair [array length, GLint of the uniform location]
-
- // If an uniform with this name exists, and if its index is within the array limits (if it's even an array),
- // query the WebGLlocation, or return an existing cached location.
- if (sizeAndId && arrayIndex < sizeAndId[0]) {
- arrayIndex += sizeAndId[1]; // Add the base location of the uniform to the array index offset.
- if ((uniformLocsById[arrayIndex] = uniformLocsById[arrayIndex] || GLctx.getUniformLocation(program, name))) {
- return arrayIndex;
- }
+ var uniformInfo = GL.programInfos[program] && GL.programInfos[program].uniforms[name]; // returns pair [ dimension_of_uniform_array, uniform_location ]
+ if (uniformInfo && arrayIndex >= 0 && arrayIndex < uniformInfo[0]) { // Check if user asked for an out-of-bounds element, i.e. for 'vec4 colors[3];' user could ask for 'colors[10]' which should return -1.
+ return uniformInfo[1] + arrayIndex;
+ } else {
+ return -1;
}
- return -1;
}
function _glLinkProgram(program) {
- program = GL.programs[program];
- GLctx.linkProgram(program);
- // Invalidate earlier computed uniform->ID mappings, those have now become stale
- program.uniformLocsById = 0; // Mark as null-like so that glGetUniformLocation() knows to populate this again.
- program.uniformSizeAndIdsByName = {};
-
+ GLctx.linkProgram(GL.programs[program]);
+ GL.populateUniformTable(program);
}
function _glShaderSource(shader, count, string, length) {
@@ -2796,25 +2757,11 @@ var ASM_CONSTS = {
GLctx.shaderSource(GL.shaders[shader], source);
}
- function webglGetUniformLocation(location) {
- var p = GLctx.currentProgram;
- var webglLoc = p.uniformLocsById[location];
- // p.uniformLocsById[location] stores either an integer, or a WebGLUniformLocation.
-
- // If an integer, we have not yet bound the location, so do it now. The integer value specifies the array index
- // we should bind to.
- if (webglLoc >= 0) {
- p.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(p, p.uniformArrayNamesById[location] + (webglLoc > 0 ? '[' + webglLoc + ']' : ''));
- }
- // Else an already cached WebGLUniformLocation, return it.
- return webglLoc;
- }
-
var miniTempWebGLFloatBuffers=[];
function _glUniformMatrix4fv(location, count, transpose, value) {
if (GL.currentContext.version >= 2) { // WebGL 2 provides new garbage-free entry points to call to WebGL. Use those always when possible.
- GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value>>2, count*16);
+ GLctx.uniformMatrix4fv(GL.uniforms[location], !!transpose, HEAPF32, value>>2, count*16);
return;
}
@@ -2847,15 +2794,11 @@ var ASM_CONSTS = {
{
var view = HEAPF32.subarray((value)>>2, (value+count*64)>>2);
}
- GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, view);
+ GLctx.uniformMatrix4fv(GL.uniforms[location], !!transpose, view);
}
function _glUseProgram(program) {
- program = GL.programs[program];
- GLctx.useProgram(program);
- // Record the currently active program so that we can access the uniform
- // mapping table of that program.
- GLctx.currentProgram = program;
+ GLctx.useProgram(GL.programs[program]);
}
function _glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
@@ -2921,6 +2864,7 @@ 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_mousemove_callback_on_thread": _emscripten_set_mousemove_callback_on_thread,
"emscripten_webgl_create_context": _emscripten_webgl_create_context,
"emscripten_webgl_init_context_attributes": _emscripten_webgl_init_context_attributes,
"emscripten_webgl_make_context_current": _emscripten_webgl_make_context_current,
@@ -3066,10 +3010,6 @@ if (!Object.getOwnPropertyDescriptor(Module, "ENV")) Module["ENV"] = function()
if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_CODES")) Module["ERRNO_CODES"] = function() { abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_MESSAGES")) Module["ERRNO_MESSAGES"] = function() { abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "setErrNo")) Module["setErrNo"] = function() { abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetPton4")) Module["inetPton4"] = function() { abort("'inetPton4' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetNtop4")) Module["inetNtop4"] = function() { abort("'inetNtop4' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetPton6")) Module["inetPton6"] = function() { abort("'inetPton6' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "inetNtop6")) Module["inetNtop6"] = function() { abort("'inetNtop6' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "readSockaddr")) Module["readSockaddr"] = function() { abort("'readSockaddr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "writeSockaddr")) Module["writeSockaddr"] = function() { abort("'writeSockaddr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "DNS")) Module["DNS"] = function() { abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
@@ -3093,12 +3033,7 @@ if (!Object.getOwnPropertyDescriptor(Module, "dynCallLegacy")) Module["dynCallLe
if (!Object.getOwnPropertyDescriptor(Module, "getDynCaller")) Module["getDynCaller"] = function() { abort("'getDynCaller' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "dynCall")) Module["dynCall"] = function() { abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "callRuntimeCallbacks")) Module["callRuntimeCallbacks"] = function() { abort("'callRuntimeCallbacks' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "runtimeKeepaliveCounter")) Module["runtimeKeepaliveCounter"] = function() { abort("'runtimeKeepaliveCounter' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "keepRuntimeAlive")) Module["keepRuntimeAlive"] = function() { abort("'keepRuntimeAlive' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "runtimeKeepalivePush")) Module["runtimeKeepalivePush"] = function() { abort("'runtimeKeepalivePush' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "runtimeKeepalivePop")) Module["runtimeKeepalivePop"] = function() { abort("'runtimeKeepalivePop' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "callUserCallback")) Module["callUserCallback"] = function() { abort("'callUserCallback' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "maybeExit")) Module["maybeExit"] = function() { abort("'maybeExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
+if (!Object.getOwnPropertyDescriptor(Module, "abortStackOverflow")) Module["abortStackOverflow"] = function() { abort("'abortStackOverflow' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "reallyNegative")) Module["reallyNegative"] = function() { abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "unSign")) Module["unSign"] = function() { abort("'unSign' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "reSign")) Module["reSign"] = function() { abort("'reSign' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
@@ -3199,7 +3134,6 @@ if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGet")) Module["emsc
if (!Object.getOwnPropertyDescriptor(Module, "computeUnpackAlignedImageSize")) Module["computeUnpackAlignedImageSize"] = function() { abort("'computeUnpackAlignedImageSize' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetTexPixelData")) Module["emscriptenWebGLGetTexPixelData"] = function() { abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetUniform")) Module["emscriptenWebGLGetUniform"] = function() { abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
-if (!Object.getOwnPropertyDescriptor(Module, "webglGetUniformLocation")) Module["webglGetUniformLocation"] = function() { abort("'webglGetUniformLocation' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetVertexAttrib")) Module["emscriptenWebGLGetVertexAttrib"] = function() { abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetBufferBinding")) Module["emscriptenWebGLGetBufferBinding"] = function() { abort("'emscriptenWebGLGetBufferBinding' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLValidateMapBufferTarget")) Module["emscriptenWebGLValidateMapBufferTarget"] = function() { abort("'emscriptenWebGLValidateMapBufferTarget' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
@@ -3289,6 +3223,7 @@ function callMain(args) {
return;
} else if (e == 'unwind') {
// running an evented main loop, don't immediately exit
+ noExitRuntime = true;
return;
} else {
var toLog = e;
@@ -3398,19 +3333,17 @@ function checkUnflushedContent() {
/** @param {boolean|number=} implicit */
function exit(status, implicit) {
- EXITSTATUS = status;
-
checkUnflushedContent();
// if this is just main exit-ing implicitly, and the status is 0, then we
// don't need to do anything here and can just leave. if the status is
// non-zero, though, then we need to report it.
// (we may have warned about this earlier, if a situation justifies doing so)
- if (implicit && keepRuntimeAlive() && status === 0) {
+ if (implicit && noExitRuntime && status === 0) {
return;
}
- if (keepRuntimeAlive()) {
+ if (noExitRuntime) {
// if exit() was called, we may warn the user if the runtime isn't actually being shut down
if (!implicit) {
var msg = 'program exited (with status: ' + status + '), but EXIT_RUNTIME is not set, so halting execution but not exiting the runtime or preventing further async execution (build with EXIT_RUNTIME=1, if you want a true shutdown)';
@@ -3418,6 +3351,8 @@ function exit(status, implicit) {
}
} else {
+ EXITSTATUS = status;
+
exitRuntime();
if (Module['onExit']) Module['onExit'](status);
diff --git a/2d/rigidbody/rigidbody_1/dist/output.wasm b/2d/rigidbody/rigidbody_1/dist/output.wasm
index 2a9924f..c091140 100755
Binary files a/2d/rigidbody/rigidbody_1/dist/output.wasm and b/2d/rigidbody/rigidbody_1/dist/output.wasm differ
diff --git a/2d/rigidbody/rigidbody_1/main.cpp b/2d/rigidbody/rigidbody_1/main.cpp
index 26d24e2..8d4ab0e 100644
--- a/2d/rigidbody/rigidbody_1/main.cpp
+++ b/2d/rigidbody/rigidbody_1/main.cpp
@@ -43,6 +43,8 @@ struct Rigidbody {
struct Rectangle {
OrthographicShape shape;
Rigidbody body;
+ Vector2 originalPoints[4];
+ Vector2 transformedPoints[4];
void load(OrthographicRenderer* renderer, Vector4 color, float32 width, float32 height) {
color = color.toNormalizedColor();
@@ -62,6 +64,11 @@ struct Rectangle {
vertices[i].color = color;
}
+ originalPoints[0] = vertices[0].position;
+ originalPoints[1] = vertices[1].position;
+ originalPoints[2] = vertices[2].position;
+ originalPoints[3] = vertices[4].position;
+
shape.load(vertices, 6, renderer);
body.reset();
}
@@ -69,6 +76,54 @@ struct Rectangle {
void update(float32 dtSeconds) {
body.update(dtSeconds);
shape.model = Mat4x4().translateByVec2(body.position);
+
+ // Note: This helps us check if the cursor is within the bounds of the
+ // rectangle later on.
+ for (int idx = 0; idx < 4; idx++) {
+ transformedPoints[idx] = shape.model * originalPoints[idx];
+ }
+ }
+
+ void render(OrthographicRenderer* renderer) {
+ shape.render(renderer);
+ }
+
+ void unload() {
+ shape.unload();
+ }
+};
+
+struct Circle {
+ OrthographicShape shape;
+ Rigidbody body;
+
+ float32 radius = 5.f;
+
+ void load(OrthographicRenderer* renderer, Vector4 color) {
+ const int32 numSegments = 36;
+ const float32 radiansPerSegment = (2.f * PI) / static_cast(numSegments);
+ const int32 numVertices = numSegments * 3;
+
+ color = color.toNormalizedColor();
+
+ OrthographicVertex vertices[numSegments * 3];
+ for (int idx = 0; idx < numSegments; idx++) {
+ int vIdx = idx * 3;
+
+ vertices[vIdx].color = color;
+ vertices[vIdx].position = Vector2 { radius * cosf(radiansPerSegment * idx), radius * sinf(radiansPerSegment * idx) };
+ vertices[vIdx + 1].color = color;
+ vertices[vIdx + 1].position = Vector2 { 0.f, 0.f };
+ vertices[vIdx + 2].color = color;
+ vertices[vIdx + 2].position = Vector2 { radius * cosf(radiansPerSegment * (idx + 1)), radius * sinf(radiansPerSegment * (idx + 1)) };
+ }
+
+ shape.load(vertices, numVertices, renderer);
+ body.reset();
+ }
+
+ void update(float32 dtSeconds) {
+ shape.model = Mat4x4().translateByVec2(body.position);
}
void render(OrthographicRenderer* renderer) {
@@ -82,6 +137,7 @@ struct Rectangle {
EM_BOOL onPlayClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData);
EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, void* userData);
+EM_BOOL onMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
void load();
void update(float32 time, void* userData);
@@ -91,11 +147,15 @@ WebglContext context;
OrthographicRenderer renderer;
MainLoop mainLoop;
Rectangle rectangle;
+Circle pointer;
+bool isIntersectingPointer = false;
int main() {
context.init("#gl_canvas");
emscripten_set_click_callback("#gl_canvas_play", NULL, false, onPlayClicked);
emscripten_set_click_callback("#gl_canvas_stop", NULL, false, onStopClicked);
+ emscripten_set_mousemove_callback("#gl_canvas", NULL, false, onMouseMove);
+
return 0;
}
@@ -106,11 +166,40 @@ void load() {
rectangle.body.position = Vector2 { context.width / 3.f, context.height / 3.f };
rectangle.body.velocity = Vector2 { 100.f, 250.f };
+ pointer.load(&renderer, Vector4 { 25.f, 235.f, 235.f, 255.f });
+
mainLoop.run(update);
}
+bool isPointInRectangle(Vector2 p, Rectangle r) {
+ // https://math.stackexchange.com/a/190373
+ Vector2 A = r.transformedPoints[0];
+ Vector2 B = r.transformedPoints[1];
+ Vector2 D = r.transformedPoints[3];
+
+ float32 amDotAb = (p - A).dot(B - A);
+ float32 abDotAb = (B - A).dot(B - A);
+
+ float32 amDotAd = (p - A).dot(D - A);
+ float32 aDDotAd = (D - A).dot(D - A);
+
+ return amDotAb > 0 && amDotAb < abDotAb && amDotAd > 0 && amDotAd < aDDotAd;
+
+}
+
void update(float32 deltaTimeSeconds, void* userData) {
rectangle.update(deltaTimeSeconds);
+ pointer.update(deltaTimeSeconds);
+
+ if (isPointInRectangle(pointer.body.position, rectangle)) {
+ if (!isIntersectingPointer) {
+ isIntersectingPointer = true;
+ rectangle.body.force += pointer.body.force;
+ }
+ } else if (isIntersectingPointer) {
+ isIntersectingPointer = false;
+ }
+
// Check collisions with walls so we don't go out of the scene. Simply reflect here.
if (rectangle.body.position.x <= 0.f) {
@@ -121,24 +210,26 @@ void update(float32 deltaTimeSeconds, void* userData) {
rectangle.body.position.y = 0.f;
rectangle.body.velocity = rectangle.body.velocity - Vector2 { 0.f, 1.f } * (2 * (rectangle.body.velocity.dot(Vector2 { 0.f, 1.f })));
}
- if (rectangle.body.position.x >= 640.f) {
- rectangle.body.position.x = 640.f;
+ if (rectangle.body.position.x >= 800.f) {
+ rectangle.body.position.x = 800.f;
rectangle.body.velocity = rectangle.body.velocity - Vector2 { -1.f, 0.f } * (2 * (rectangle.body.velocity.dot(Vector2{ -1.f, 0.f })));
}
- if (rectangle.body.position.y >= 480.f) {
- rectangle.body.position.y = 480.f;
+ if (rectangle.body.position.y >= 600.f) {
+ rectangle.body.position.y = 600.f;
rectangle.body.velocity = rectangle.body.velocity - Vector2 { 0.f, -1.f } * (2 * (rectangle.body.velocity.dot(Vector2 { 0.f, -1.f }))) ;
}
// Renderer
renderer.render();
rectangle.render(&renderer);
+ pointer.render(&renderer);
}
void unload() {
mainLoop.stop();
renderer.unload();
rectangle.unload();
+ pointer.unload();
}
//
@@ -156,3 +247,17 @@ EM_BOOL onStopClicked(int eventType, const EmscriptenMouseEvent* mouseEvent, voi
unload();
return true;
}
+
+EM_BOOL onMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) {
+ if (!mainLoop.isRunning) {
+ return true;
+ }
+
+ pointer.body.force.x = static_cast(mouseEvent->movementX) * 1000.f;
+ pointer.body.force.y = static_cast(-mouseEvent->movementY) * 1000.f;
+
+ pointer.body.position.x = static_cast(mouseEvent->targetX);
+ pointer.body.position.y = static_cast(600.f - mouseEvent->targetY);
+
+ return true;
+}
diff --git a/_wasm/intro/intro.cpp b/_wasm/intro/intro.cpp
index 63c80ef..8e1574b 100644
--- a/_wasm/intro/intro.cpp
+++ b/_wasm/intro/intro.cpp
@@ -112,7 +112,7 @@ EM_BOOL terminateScene(int eventType, const EmscriptenMouseEvent* mouseEvent, vo
int main() {
printf("Initializing the canvas...\n");
- emscripten_set_canvas_element_size( "#wasm_canvas", 640, 480 );
+ emscripten_set_canvas_element_size( "#wasm_canvas", 800, 600 );
EmscriptenWebGLContextAttributes attrs;
emscripten_webgl_init_context_attributes(&attrs);
@@ -160,10 +160,10 @@ EM_BOOL runScene(int eventType, const EmscriptenMouseEvent* mouseEvent, void* us
scene.triangleObject.vertices[0] = { Vector2 { -100, -50 }, Vector4 { 1.f, 0.f, 0.f, 1.f }};
scene.triangleObject.vertices[1] = { Vector2 { 0, 50 }, Vector4 { 0.f, 1.f, 0.f, 1.f }};
scene.triangleObject.vertices[2] = { Vector2 { 100, -50 }, Vector4 { 0.f, 0.f, 1.f, 1.f }};
- scene.triangleObject.position = { 320.f, 480.f - 100.f };
+ scene.triangleObject.position = { 320.f, 600.f - 100.f };
scene.triangleObject.initialize(&scene.programData);
- scene.projection = Mat4x4().getOrthographicMatrix(0, 640, 0, 480);
+ scene.projection = Mat4x4().getOrthographicMatrix(0, 800, 0, 600);
scene.isTerminated = false;
printf("Scene initialized.\n");
diff --git a/_wasm/intro/intro.html b/_wasm/intro/intro.html
index 92a6ea8..a5ac225 100644
--- a/_wasm/intro/intro.html
+++ b/_wasm/intro/intro.html
@@ -38,7 +38,7 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.