diff --git a/examples/files.js b/examples/files.js index ce94f797941316..2e8898c9993268 100644 --- a/examples/files.js +++ b/examples/files.js @@ -118,6 +118,7 @@ var files = { "webgl_loader_texture_exr", "webgl_loader_texture_hdr", "webgl_loader_texture_ktx", + "webgl_loader_texture_ktx2", "webgl_loader_texture_pvrtc", "webgl_loader_texture_rgbm", "webgl_loader_texture_tga", diff --git a/examples/js/libs/basis/README.md b/examples/js/libs/basis/README.md index 0c9961a3d8a262..8451f57ded00c6 100644 --- a/examples/js/libs/basis/README.md +++ b/examples/js/libs/basis/README.md @@ -7,9 +7,19 @@ a wide variety of GPU texture compression formats. [GitHub](https://github.com/BinomialLLC/basis_universal) -## Contents +## Transcoders -This folder contains two files: +Basis Universal texture data may be used in two different file formats: +`.basis` and `.ktx2`. Texture data is identical in both cases, but different +transcoders are required to read the two file types. Both transcoders are +available in this folder now, but they may be merged in the future. + +For further documentation about the Basis compressor and transcoder, refer to +the [Basis GitHub repository](https://github.com/BinomialLLC/basis_universal). + +### .basis + +The folder contains two files required for transcoding `.basis` textures: * `basis_transcoder.js` — JavaScript wrapper for the WebAssembly transcoder. * `basis_transcoder.wasm` — WebAssembly transcoder. @@ -35,8 +45,17 @@ basisLoader.load( 'diffuse.basis', function ( texture ) { } ); ``` -For further documentation about the Basis compressor and transcoder, refer to -the [Basis GitHub repository](https://github.com/BinomialLLC/basis_universal). +### .ktx2 + +The folder contains two files required for transcoding `.ktx2` textures: + +* `msc_basis_transcoder.js` — JavaScript wrapper for the WebAssembly transcoder. +* `msc_basis_transcoder.wasm` — WebAssembly transcoder. + +Currently, the `msc_basis_transcoder.js` file must be added to the page as a +global script. The WASM transcoder will be downloaded from the same directory +automatically. These will likely be replaced with ES modules, and merged with +the `.basis` transcoder, in the future. See `KTX2Loader` for usage. ## License diff --git a/examples/js/libs/basis/msc_basis_transcoder.js b/examples/js/libs/basis/msc_basis_transcoder.js new file mode 100755 index 00000000000000..8d75ebe3dccaec --- /dev/null +++ b/examples/js/libs/basis/msc_basis_transcoder.js @@ -0,0 +1,21 @@ + +var MSC_TRANSCODER = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + return ( +function(MSC_TRANSCODER) { + MSC_TRANSCODER = MSC_TRANSCODER || {}; + +var Module=typeof MSC_TRANSCODER!=="undefined"?MSC_TRANSCODER:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename);return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var asm2wasmImports={"f64-rem":function(x,y){return x%y},"debugger":function(){}};var functionPointers=new Array(0);var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected")}var wasmMemory;var wasmTable;var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(u8Array[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var DYNAMIC_BASE=5770592,DYNAMICTOP_PTR=527680;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_TOTAL_MEMORY/WASM_PAGE_SIZE})}if(wasmMemory){buffer=wasmMemory.buffer}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var wasmBinaryFile="msc_basis_transcoder.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary())})}function createWasm(env){var info={"env":env,"global":{"NaN":NaN,Infinity:Infinity},"global.Math":Math,"asm2wasm":asm2wasmImports};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return{}}Module["asm"]=function(global,env,providedBuffer){env["memory"]=wasmMemory;env["table"]=wasmTable=new WebAssembly.Table({"initial":366,"maximum":366,"element":"anyfunc"});env["__memory_base"]=1024;env["__table_base"]=0;var exports=createWasm(env);return exports};__ATINIT__.push({func:function(){__GLOBAL__sub_I_transcoder_wrapper_cpp()}},{func:function(){__GLOBAL__sub_I_bind_cpp()}});function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function ___cxa_allocate_exception(size){return _malloc(size)}var ___exception_infos={};function ___cxa_pure_virtual(){ABORT=true;throw"Pure virtual function called!"}var ___exception_last=0;function ___cxa_throw(ptr,type,destructor){___exception_infos[ptr]={ptr:ptr,adjusted:[ptr],type:type,destructor:destructor,refcount:0,caught:false,rethrown:false};___exception_last=ptr;if(!("uncaught_exception"in __ZSt18uncaught_exceptionv)){__ZSt18uncaught_exceptionv.uncaught_exceptions=1}else{__ZSt18uncaught_exceptionv.uncaught_exceptions++}throw ptr}function ___cxa_uncaught_exceptions(){return __ZSt18uncaught_exceptionv.uncaught_exceptions}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};var SYSCALLS={buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:0,get:function(varargs){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(){var ret=UTF8ToString(SYSCALLS.get());return ret},get64:function(){var low=SYSCALLS.get(),high=SYSCALLS.get();return low},getZero:function(){SYSCALLS.get()}};function ___syscall140(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),offset_high=SYSCALLS.get(),offset_low=SYSCALLS.get(),result=SYSCALLS.get(),whence=SYSCALLS.get();return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall146(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.get(),iov=SYSCALLS.get(),iovcnt=SYSCALLS.get();var ret=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j=char_0&&f<=char_9){return"_"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\n"+' "use strict";'+" return body.apply(this, arguments);\n"+"};\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i>shift])},destructorFunction:null})}function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right}function shallowCopyInternalPointer(o){return{count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType}}function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")}var finalizationGroup=false;function detachFinalizer(handle){}function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}}function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}}function attachFinalizer(handle){if("undefined"===typeof FinalizationGroup){attachFinalizer=function(handle){return handle};return handle}finalizationGroup=new FinalizationGroup(function(iter){for(var result=iter.next();!result.done;result=iter.next()){var $$=result.value;if(!$$.ptr){console.warn("object already deleted: "+$$.ptr)}else{releaseClassHandle($$)}}});attachFinalizer=function(handle){finalizationGroup.register(handle,handle.$$,handle.$$);return handle};detachFinalizer=function(handle){finalizationGroup.unregister(handle.$$)};return attachFinalizer(handle)}function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}}function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}}function ClassHandle_isDeleted(){return!this.$$.ptr}var delayFunction=undefined;var deletionQueue=[];function flushPendingDeletes(){while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}}function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHandle_isAliasOf;ClassHandle.prototype["clone"]=ClassHandle_clone;ClassHandle.prototype["delete"]=ClassHandle_delete;ClassHandle.prototype["isDeleted"]=ClassHandle_isDeleted;ClassHandle.prototype["deleteLater"]=ClassHandle_deleteLater}function ClassHandle(){}var registeredPointers={};function ensureOverloadTable(proto,methodName,humanName){if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError("Function '"+humanName+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+proto[methodName].overloadTable+")!")}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}}function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError("Cannot register public name '"+name+"' twice")}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError("Cannot register multiple overloads of a function with the same number of arguments ("+numArguments+")!")}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}}function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError("Expected null or instance of "+desiredClass.name+", got an instance of "+ptrClass.name)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr}function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,__emval_register(function(){clonedHandle["delete"]()}));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+handle.$$.ptrType.name+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr}function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.rawDestructor(ptr)}}function RegisteredPointer_deleteObject(handle){if(handle!==null){handle["delete"]()}}function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)}function getInheritedInstanceCount(){return Object.keys(registeredInstances).length}function getLiveInheritedInstances(){var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv}function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}}function init_embind(){Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction}var registeredInstances={};function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr}function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]}function makeClassHandle(prototype,record){if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record}}))}function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee=RegisteredPointer_getPointee;RegisteredPointer.prototype.destructor=RegisteredPointer_destructor;RegisteredPointer.prototype["argPackAdvance"]=8;RegisteredPointer.prototype["readValueFromPointer"]=simpleReadValueFromPointer;RegisteredPointer.prototype["deleteObject"]=RegisteredPointer_deleteObject;RegisteredPointer.prototype["fromWireType"]=RegisteredPointer_fromWireType}function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function embind__requireFunction(signature,rawFunction){signature=readLatin1String(signature);function makeDynCaller(dynCall){var args=[];for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i>2)+i])}return array}function __embind_register_class_class_function(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn){var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=readLatin1String(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker);whenDependentTypesAreResolved([],[rawClassType],function(classType){classType=classType[0];var humanName=classType.name+"."+methodName;function unboundTypesHandler(){throwUnboundTypeError("Cannot call "+humanName+" due to unbound types",rawArgTypes)}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn);if(undefined===proto[methodName].overloadTable){func.argCount=argCount-1;proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}return[]});return[]})}function __embind_register_class_constructor(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor){var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],function(classType){classType=classType[0];var humanName="constructor "+classType.name;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError("Cannot register multiple constructors with identical number of parameters ("+(argCount-1)+") for class '"+classType.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!")}classType.registeredClass.constructor_body[argCount-1]=function unboundTypeHandler(){throwUnboundTypeError("Cannot construct "+classType.name+" due to unbound types",rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,function(argTypes){classType.registeredClass.constructor_body[argCount-1]=function constructor_body(){if(arguments.length!==argCount-1){throwBindingError(humanName+" called with "+arguments.length+" arguments, expected "+(argCount-1))}var destructors=[];var args=new Array(argCount);args[0]=rawConstructor;for(var i=1;i4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i>1])};case 2:return function(pointer){var heap=signed?HEAP32:HEAPU32;return this["fromWireType"](heap[pointer>>2])};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_enum(rawType,name,size,isSigned){var shift=getShiftFromSize(size);name=readLatin1String(name);function ctor(){}ctor.values={};registerType(rawType,{name:name,constructor:ctor,"fromWireType":function(c){return this.constructor.values[c]},"toWireType":function(destructors,c){return c.value},"argPackAdvance":8,"readValueFromPointer":enumReadValueFromPointer(name,shift,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor)}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+" has unknown type "+getTypeName(rawType))}return impl}function __embind_register_enum_value(rawEnumType,name,enumValue){var enumType=requireRegisteredType(rawEnumType,"enum");name=readLatin1String(name);var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(enumType.name+"_"+name,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value}function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function __embind_register_function(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn){var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError("Cannot call "+name+" due to unbound types",argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn),argCount-1);return[]})}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=function(value){return value};if(minRange===0){var bitshift=32-8*size;fromWireType=function(value){return value<>>bitshift}}var isUnsignedType=name.indexOf("unsigned")!=-1;registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}if(valuemaxRange){throw new TypeError('Passing a number "'+_embind_repr(value)+'" from JS side to C/C++ side to an argument of type "'+name+'", which is outside the valid range ['+minRange+", "+maxRange+"]!")}return isUnsignedType?value>>>0:value|0},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(heap["buffer"],data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var str;if(stdStringIsUTF8){var endChar=HEAPU8[value+4+length];var endCharSwap=0;if(endChar!=0){endCharSwap=endChar;HEAPU8[value+4+length]=0}var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i;if(HEAPU8[currentBytePtr]==0){var stringSegment=UTF8ToString(decodeStartPtr);if(str===undefined)str=stringSegment;else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}if(endCharSwap!=0)HEAPU8[value+4+length]=endCharSwap}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr+4,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+4+i]=charCode}}else{for(var i=0;i>2];var a=new Array(length);var start=value+4>>shift;for(var i=0;i>2]=length;var start=ptr+4>>shift;for(var i=0;i>2]=rd;return returnType["toWireType"](destructors,handle)}var emval_symbols={};function getStringOrSymbol(address){var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}else{return symbol}}var emval_methodCallers=[];function __emval_call_void_method(caller,handle,methodName,args){caller=emval_methodCallers[caller];handle=requireHandle(handle);methodName=getStringOrSymbol(methodName);caller(handle,methodName,null,args)}function __emval_addMethodCaller(caller){var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id}function __emval_lookupTypes(argCount,argTypes,argWireTypes){var a=new Array(argCount);for(var i=0;i>2)+i],"parameter "+i)}return a}function __emval_get_method_caller(argCount,argTypes){var types=__emval_lookupTypes(argCount,argTypes);var retType=types[0];var signatureName=retType.name+"_$"+types.slice(1).map(function(t){return t.name}).join("_")+"$";var params=["retType"];var args=[retType];var argsList="";for(var i=0;i4){emval_handle_array[handle].refcount+=1}}function craftEmvalAllocator(argCount){var argsList="";for(var i=0;i> 2) + "+i+'], "parameter '+i+'");\n'+"var arg"+i+" = argType"+i+".readValueFromPointer(args);\n"+"args += argType"+i+"['argPackAdvance'];\n"}functionBody+="var obj = new constructor("+argsList+");\n"+"return __emval_register(obj);\n"+"}\n";return new Function("requireRegisteredType","Module","__emval_register",functionBody)(requireRegisteredType,Module,__emval_register)}var emval_newers={};function __emval_new(handle,argCount,argTypes,args){handle=requireHandle(handle);var newer=emval_newers[argCount];if(!newer){newer=craftEmvalAllocator(argCount);emval_newers[argCount]=newer}return newer(handle,argTypes,args)}function __emval_new_cstring(v){return __emval_register(getStringOrSymbol(v))}function __emval_new_object(){return __emval_register({})}function __emval_run_destructors(handle){var destructors=emval_handle_array[handle].value;runDestructors(destructors);__emval_decref(handle)}function __emval_set_property(handle,key,value){handle=requireHandle(handle);key=requireHandle(key);value=requireHandle(value);handle[key]=value}function __emval_take_value(type,argv){type=requireRegisteredType(type,"_emval_take_value");var v=type["readValueFromPointer"](argv);return __emval_register(v)}function _abort(){Module["abort"]()}function _emscripten_get_heap_size(){return HEAP8.length}function _llvm_trap(){abort("trap!")}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=65536;var LIMIT=2147483648-PAGE_MULTIPLE;if(requestedSize>LIMIT){return false}var MIN_TOTAL_MEMORY=16777216;var newSize=Math.max(oldSize,MIN_TOTAL_MEMORY);while(newSize0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); + + + return MSC_TRANSCODER +} +); +})(); +if (typeof exports === 'object' && typeof module === 'object') + module.exports = MSC_TRANSCODER; + else if (typeof define === 'function' && define['amd']) + define([], function() { return MSC_TRANSCODER; }); + else if (typeof exports === 'object') + exports["MSC_TRANSCODER"] = MSC_TRANSCODER; + \ No newline at end of file diff --git a/examples/js/libs/basis/msc_basis_transcoder.wasm b/examples/js/libs/basis/msc_basis_transcoder.wasm new file mode 100644 index 00000000000000..305f0756a8c97b Binary files /dev/null and b/examples/js/libs/basis/msc_basis_transcoder.wasm differ diff --git a/examples/jsm/loaders/KTX2Loader.js b/examples/jsm/loaders/KTX2Loader.js new file mode 100644 index 00000000000000..5370e8af16064d --- /dev/null +++ b/examples/jsm/loaders/KTX2Loader.js @@ -0,0 +1,695 @@ +/** + * @author donmccurdy / https://www.donmccurdy.com + * @author MarkCallow / https://github.com/MarkCallow + * + * References: + * - KTX: http://github.khronos.org/KTX-Specification/ + * - DFD: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#basicdescriptor + * + * To do: + * - [ ] Cross-platform testing + * - [ ] Specify JS/WASM transcoder path + * - [ ] High-quality demo + * - [ ] Documentation + * - [ ] TypeScript definitions + * - [ ] (Optional) Include BC5 + * - [ ] (Optional) Include EAC RG on mobile (WEBGL_compressed_texture_etc) + * - [ ] (Optional) Include two-texture output mode (see: clearcoat + clearcoatRoughness) + * - [ ] (Optional) Support Web Workers, after #18234 + */ + +import { + CompressedTexture, + CompressedTextureLoader, + FileLoader, + LinearEncoding, + LinearFilter, + LinearMipmapLinearFilter, + RGB_ETC1_Format, + RGB_ETC2_Format, + RGBA_ETC2_EAC_Format, + RGB_PVRTC_4BPPV1_Format, + RGB_S3TC_DXT1_Format, + RGBA_ASTC_4x4_Format, + RGBA_PVRTC_4BPPV1_Format, + RGBA_S3TC_DXT5_Format, + sRGBEncoding, + UnsignedByteType, +} from '../../../build/three.module.js'; + +// Data Format Descriptor (DFD) constants. + +const DFDModel = { + ETC1S: 163, + UASTC: 166, +} + +const DFDChannel = { + ETC1S: { + RGB: 0, + RRR: 3, + GGG: 4, + AAA: 15, + }, + UASTC: { + RGB: 0, + RGBA: 3, + RRR: 4, + RRRG: 5 + }, +}; + +// + +class KTX2Loader extends CompressedTextureLoader { + + constructor ( manager ) { + + super( manager ); + + this.basisModule = null; + + this.transcoderConfig = {}; + + } + + detectSupport ( renderer ) { + + this.transcoderConfig = { + astcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_astc' ), + etc1Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc1' ), + etc2Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc' ), + dxtSupported: renderer.extensions.has( 'WEBGL_compressed_texture_s3tc' ), + pvrtcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_pvrtc' ) + || renderer.extensions.has( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ) + }; + + return this; + + } + + init () { + + var scope = this; + + // The Emscripten wrapper returns a fake Promise, which can cause + // infinite recursion when mixed with native Promises. Wrap the module + // initialization to return a native Promise. + return new Promise( function ( resolve ) { + + MSC_TRANSCODER().then( function ( basisModule ) { + + scope.basisModule = basisModule; + + basisModule.initTranscoders(); + + resolve(); + + } ); + + } ); + + } + + load ( url, onLoad, onProgress, onError ) { + + var scope = this; + + var texture = new CompressedTexture(); + + var bufferPending = new Promise( function (resolve, reject ) { + + new FileLoader( scope.manager ) + .setPath( scope.path ) + .setResponseType( 'arraybuffer' ) + .load( url, resolve, onProgress, reject ); + + } ); + + Promise.all( [ bufferPending, this.init() ] ).then( function ( [ buffer ] ) { + + scope.parse( buffer, function ( _texture ) { + + texture.copy( _texture ); + texture.needsUpdate = true; + + if ( onLoad ) onLoad( texture ); + + }, onError ); + + } ); + + return texture; + + } + + parse ( buffer, onLoad, onError ) { + + var BasisLzEtc1sImageTranscoder = this.basisModule.BasisLzEtc1sImageTranscoder; + var UastcImageTranscoder = this.basisModule.UastcImageTranscoder; + var TextureFormat = this.basisModule.TextureFormat; + + var ktx = new KTX2Container( this.basisModule, buffer ); + + // TODO(donmccurdy): Should test if texture is transcodable before attempting + // any transcoding. If supercompressionScheme is KTX_SS_BASIS_LZ and dfd + // colorModel is ETC1S (163) or if dfd colorModel is UASTCF (166) + // then texture must be transcoded. + var transcoder = ktx.getTexFormat() === TextureFormat.UASTC4x4 + ? new UastcImageTranscoder() + : new BasisLzEtc1sImageTranscoder(); + + ktx.initMipmaps( transcoder, this.transcoderConfig ) + .then( function () { + + var texture = new CompressedTexture( + ktx.mipmaps, + ktx.getWidth(), + ktx.getHeight(), + ktx.transcodedFormat, + UnsignedByteType + ); + + texture.encoding = ktx.getEncoding(); + texture.premultiplyAlpha = ktx.getPremultiplyAlpha(); + texture.minFilter = ktx.mipmaps.length === 1 ? LinearFilter : LinearMipmapLinearFilter; + texture.magFilter = LinearFilter; + + onLoad( texture ); + + } ) + .catch( onError ); + + return this; + + } + +} + +class KTX2Container { + + constructor ( basisModule, arrayBuffer ) { + + this.basisModule = basisModule; + this.arrayBuffer = arrayBuffer; + + this.mipmaps = null; + this.transcodedFormat = null; + + // Confirm this is a KTX 2.0 file, based on the identifier in the first 12 bytes. + var idByteLength = 12; + var id = new Uint8Array( this.arrayBuffer, 0, idByteLength ); + if ( id[ 0 ] !== 0xAB || // '´' + id[ 1 ] !== 0x4B || // 'K' + id[ 2 ] !== 0x54 || // 'T' + id[ 3 ] !== 0x58 || // 'X' + id[ 4 ] !== 0x20 || // ' ' + id[ 5 ] !== 0x32 || // '2' + id[ 6 ] !== 0x30 || // '0' + id[ 7 ] !== 0xBB || // 'ª' + id[ 8 ] !== 0x0D || // '\r' + id[ 9 ] !== 0x0A || // '\n' + id[ 10 ] !== 0x1A || // '\x1A' + id[ 11 ] !== 0x0A // '\n' + ) { + + throw new Error( 'THREE.KTX2Loader: Missing KTX 2.0 identifier.' ); + + } + + // TODO(donmccurdy): If we need to support BE, derive this from typeSize. + var littleEndian = true; + + + /////////////////////////////////////////////////// + // Header. + /////////////////////////////////////////////////// + + var headerByteLength = 17 * Uint32Array.BYTES_PER_ELEMENT; + var headerReader = new KTX2BufferReader( this.arrayBuffer, idByteLength, headerByteLength, littleEndian ); + + this.header = { + + vkFormat: headerReader.nextUint32(), + typeSize: headerReader.nextUint32(), + pixelWidth: headerReader.nextUint32(), + pixelHeight: headerReader.nextUint32(), + pixelDepth: headerReader.nextUint32(), + arrayElementCount: headerReader.nextUint32(), + faceCount: headerReader.nextUint32(), + levelCount: headerReader.nextUint32(), + + supercompressionScheme: headerReader.nextUint32(), + + dfdByteOffset: headerReader.nextUint32(), + dfdByteLength: headerReader.nextUint32(), + kvdByteOffset: headerReader.nextUint32(), + kvdByteLength: headerReader.nextUint32(), + sgdByteOffset: headerReader.nextUint64(), + sgdByteLength: headerReader.nextUint64(), + + }; + + if ( this.header.pixelDepth > 0 ) { + + throw new Error( 'THREE.KTX2Loader: Only 2D textures are currently supported.' ); + + } + + if ( this.header.arrayElementCount > 1 ) { + + throw new Error( 'THREE.KTX2Loader: Array textures are not currently supported.' ); + + } + + if ( this.header.faceCount > 1 ) { + + throw new Error( 'THREE.KTX2Loader: Cube textures are not currently supported.' ); + + } + + + /////////////////////////////////////////////////// + // Level index + /////////////////////////////////////////////////// + + var levelByteLength = this.header.levelCount * 3 * 8; + var levelReader = new KTX2BufferReader( this.arrayBuffer, idByteLength + headerByteLength, levelByteLength, littleEndian ); + + this.levels = []; + + for ( var i = 0; i < this.header.levelCount; i ++ ) { + + this.levels.push( { + + byteOffset: levelReader.nextUint64(), + byteLength: levelReader.nextUint64(), + uncompressedByteLength: levelReader.nextUint64(), + + } ); + + } + + + /////////////////////////////////////////////////// + // Data Format Descriptor (DFD) + /////////////////////////////////////////////////// + + var dfdReader = new KTX2BufferReader( + this.arrayBuffer, + this.header.dfdByteOffset, + this.header.dfdByteLength, + littleEndian + ); + + const sampleStart = 6; + const sampleWords = 4; + + this.dfd = { + + vendorId: dfdReader.skip( 4 /* totalSize */ ).nextUint16(), + versionNumber: dfdReader.skip( 2 /* descriptorType */ ).nextUint16(), + descriptorBlockSize: dfdReader.nextUint16(), + colorModel: dfdReader.nextUint8(), + colorPrimaries: dfdReader.nextUint8(), + transferFunction: dfdReader.nextUint8(), + flags: dfdReader.nextUint8(), + texelBlockDimension: { + x: dfdReader.nextUint8() + 1, + y: dfdReader.nextUint8() + 1, + z: dfdReader.nextUint8() + 1, + w: dfdReader.nextUint8() + 1, + }, + bytesPlane0: dfdReader.nextUint8(), + numSamples: 0, + samples: [], + + }; + + this.dfd.numSamples = ( this.dfd.descriptorBlockSize / 4 - sampleStart ) / sampleWords; + + dfdReader.skip( 7 /* bytesPlane[1-7] */ ); + + for ( var i = 0; i < this.dfd.numSamples; i++ ) { + + this.dfd.samples[i] = { + + channelID: dfdReader.skip( 3 /* bitOffset + bitLength */ ).nextUint8(), + // ... remainder not implemented. + + }; + + dfdReader.skip( 12 /* samplePosition[0-3], lower, upper */ ); + + } + + if ( this.header.vkFormat !== 0x00 /* VK_FORMAT_UNDEFINED */ && + ! ( this.header.supercompressionScheme === 1 /* BasisLZ */ || + this.dfd.colorModel === DFDModel.UASTC ) ) { + + throw new Error( 'THREE.KTX2Loader: Only Basis Universal supercompression is currently supported.' ); + + } + + + /////////////////////////////////////////////////// + // Key/Value Data (KVD) + /////////////////////////////////////////////////// + + // Not implemented. + this.kvd = {}; + + + /////////////////////////////////////////////////// + // Supercompression Global Data (SGD) + /////////////////////////////////////////////////// + + this.sgd = {}; + + if ( this.header.sgdByteLength <= 0 ) return; + + var sgdReader = new KTX2BufferReader( + this.arrayBuffer, + this.header.sgdByteOffset, + this.header.sgdByteLength, + littleEndian + ); + + this.sgd.endpointCount = sgdReader.nextUint16(); + this.sgd.selectorCount = sgdReader.nextUint16(); + this.sgd.endpointsByteLength = sgdReader.nextUint32(); + this.sgd.selectorsByteLength = sgdReader.nextUint32(); + this.sgd.tablesByteLength = sgdReader.nextUint32(); + this.sgd.extendedByteLength = sgdReader.nextUint32(); + this.sgd.imageDescs = []; + this.sgd.endpointsData = null; + this.sgd.selectorsData = null; + this.sgd.tablesData = null; + this.sgd.extendedData = null; + + for ( var i = 0; i < this.header.levelCount; i ++ ) { + + this.sgd.imageDescs.push( { + + imageFlags: sgdReader.nextUint32(), + rgbSliceByteOffset: sgdReader.nextUint32(), + rgbSliceByteLength: sgdReader.nextUint32(), + alphaSliceByteOffset: sgdReader.nextUint32(), + alphaSliceByteLength: sgdReader.nextUint32(), + + } ); + + } + + var endpointsByteOffset = this.header.sgdByteOffset + sgdReader.offset; + var selectorsByteOffset = endpointsByteOffset + this.sgd.endpointsByteLength; + var tablesByteOffset = selectorsByteOffset + this.sgd.selectorsByteLength; + var extendedByteOffset = tablesByteOffset + this.sgd.tablesByteLength; + + this.sgd.endpointsData = new Uint8Array( this.arrayBuffer, endpointsByteOffset, this.sgd.endpointsByteLength ); + this.sgd.selectorsData = new Uint8Array( this.arrayBuffer, selectorsByteOffset, this.sgd.selectorsByteLength ); + this.sgd.tablesData = new Uint8Array( this.arrayBuffer, tablesByteOffset, this.sgd.tablesByteLength ); + this.sgd.extendedData = new Uint8Array( this.arrayBuffer, extendedByteOffset, this.sgd.extendedByteLength ); + + } + + initMipmaps ( transcoder, config ) { + + var TranscodeTarget = this.basisModule.TranscodeTarget; + var TextureFormat = this.basisModule.TextureFormat; + var ImageInfo = this.basisModule.ImageInfo; + + var scope = this; + + var mipmaps = []; + var width = this.getWidth(); + var height = this.getHeight(); + var texFormat = this.getTexFormat(); + var hasAlpha = this.getAlpha(); + var isVideo = false; + + if ( texFormat === TextureFormat.ETC1S ) { + + var numEndpoints = this.sgd.endpointCount; + var numSelectors = this.sgd.selectorCount; + var endpoints = this.sgd.endpointsData; + var selectors = this.sgd.selectorsData; + var tables = this.sgd.tablesData; + + transcoder.decodePalettes( numEndpoints, endpoints, numSelectors, selectors ); + transcoder.decodeTables( tables ); + + } + + + var targetFormat; + + if ( config.astcSupported ) { + + targetFormat = TranscodeTarget.ASTC_4x4_RGBA; + this.transcodedFormat = RGBA_ASTC_4x4_Format; + + } else if ( config.dxtSupported ) { + + targetFormat = hasAlpha ? TranscodeTarget.BC3_RGBA : TranscodeTarget.BC1_RGB; + this.transcodedFormat = hasAlpha ? RGBA_S3TC_DXT5_Format : RGB_S3TC_DXT1_Format; + + } else if ( config.pvrtcSupported ) { + + targetFormat = hasAlpha ? TranscodeTarget.PVRTC1_4_RGBA : TranscodeTarget.PVRTC1_4_RGB; + this.transcodedFormat = hasAlpha ? RGBA_PVRTC_4BPPV1_Format : RGB_PVRTC_4BPPV1_Format; + + } else if ( config.etc2Supported ) { + + targetFormat = hasAlpha ? TranscodeTarget.ETC2_RGBA : TranscodeTarget.ETC1_RGB /* subset of ETC2 */; + this.transcodedFormat = hasAlpha ? RGBA_ETC2_EAC_Format : RGB_ETC2_Format; + + } else if ( config.etc1Supported ) { + + targetFormat = TranscodeTarget.ETC1_RGB; + this.transcodedFormat = RGB_ETC1_Format; + + } else { + + throw new Error( 'THREE.KTX2Loader: No suitable compressed texture format found.' ); + + } + + if ( ! this.basisModule.isFormatSupported( targetFormat, texFormat ) ) { + + throw new Error( 'THREE.KTX2Loader: Selected texture format not supported by current transcoder build.' ); + + } + + var imageDescIndex = 0; + + for ( var level = 0; level < this.header.levelCount; level ++ ) { + + var levelWidth = width / Math.pow( 2, level ); + var levelHeight = height / Math.pow( 2, level ); + + var numImagesInLevel = 1; // TODO(donmccurdy): Support cubemaps, arrays and 3D. + var imageOffsetInLevel = 0; + var imageInfo = new ImageInfo( texFormat, levelWidth, levelHeight, level ); + var levelImageByteLength = imageInfo.numBlocksX * imageInfo.numBlocksY * this.dfd.bytesPlane0; + + for ( var imageIndex = 0; imageIndex < numImagesInLevel; imageIndex ++ ) { + + var result; + var encodedData; + + if ( texFormat === TextureFormat.UASTC4x4 ) { + + // UASTC + + imageInfo.flags = 0; + imageInfo.rgbByteOffset = 0; + imageInfo.rgbByteLength = levelImageByteLength; + imageInfo.alphaByteOffset = 0; + imageInfo.alphaByteLength = 0; + + encodedData = new Uint8Array( this.arrayBuffer, this.levels[ level ].byteOffset + imageOffsetInLevel, levelImageByteLength ); + + result = transcoder.transcodeImage( targetFormat, encodedData, imageInfo, 0, hasAlpha, isVideo ); + + } else { + + // ETC1S + + var imageDesc = this.sgd.imageDescs[ imageDescIndex++ ]; + + imageInfo.flags = imageDesc.imageFlags; + imageInfo.rgbByteOffset = 0; + imageInfo.rgbByteLength = imageDesc.rgbSliceByteLength; + imageInfo.alphaByteOffset = imageDesc.alphaSliceByteOffset > 0 ? imageDesc.rgbSliceByteLength : 0; + imageInfo.alphaByteLength = imageDesc.alphaSliceByteLength; + + encodedData = new Uint8Array( this.arrayBuffer, this.levels[ level ].byteOffset + imageDesc.rgbSliceByteOffset, imageDesc.rgbSliceByteLength + imageDesc.alphaSliceByteLength ); + + result = transcoder.transcodeImage( targetFormat, encodedData, imageInfo, 0, isVideo ); + + } + + if ( result.transcodedImage === undefined ) { + + throw new Error( 'THREE.KTX2Loader: Unable to transcode image.' ); + + } + + // Transcoded image is written in memory allocated by WASM. We could avoid copying + // the image by waiting until the image is uploaded to the GPU, then calling + // delete(). However, (1) we don't know if the user will later need to re-upload it + // e.g. after calling texture.clone(), and (2) this code will eventually be in a + // Web Worker, and transferring WASM's memory seems like a very bad idea. + var levelData = result.transcodedImage.get_typed_memory_view().slice(); + result.transcodedImage.delete(); + + mipmaps.push( { data: levelData, width: levelWidth, height: levelHeight } ); + imageOffsetInLevel += levelImageByteLength; + + } + + } + + return new Promise( function ( resolve, reject ) { + + scope.mipmaps = mipmaps; + + resolve(); + + } ); + + } + + getWidth () { return this.header.pixelWidth; } + + getHeight () { return this.header.pixelHeight; } + + getEncoding () { + + return this.dfd.transferFunction === 2 /* KHR_DF_TRANSFER_SRGB */ + ? sRGBEncoding + : LinearEncoding; + + } + + getTexFormat () { + + var TextureFormat = this.basisModule.TextureFormat; + + return this.dfd.colorModel === DFDModel.UASTC ? TextureFormat.UASTC4x4 : TextureFormat.ETC1S; + + } + + getAlpha () { + + var TextureFormat = this.basisModule.TextureFormat; + + // TODO(donmccurdy): Handle all channelIDs (i.e. the R & R+G cases), + // choosing appropriate transcode target formats or providing queries + // for applications so they know what to do with the content. + + if ( this.getTexFormat() === TextureFormat.UASTC4x4 ) { + + // UASTC + + if ( ( this.dfd.samples[ 0 ].channelID & 0xF ) === DFDChannel.UASTC.RGBA ) { + + return true; + + } + + return false; + + } + + // ETC1S + + if ( this.dfd.numSamples === 2 && ( this.dfd.samples[ 1 ].channelID & 0xF ) === DFDChannel.ETC1S.AAA ) { + + return true; + + } + + return false; + + } + + getPremultiplyAlpha () { + + return !! ( this.dfd.flags & 1 /* KHR_DF_FLAG_ALPHA_PREMULTIPLIED */ ); + + } + +} + +class KTX2BufferReader { + + constructor ( arrayBuffer, byteOffset, byteLength, littleEndian ) { + + this.dataView = new DataView( arrayBuffer, byteOffset, byteLength ); + this.littleEndian = littleEndian; + this.offset = 0; + + } + + nextUint8 () { + + var value = this.dataView.getUint8( this.offset, this.littleEndian ); + + this.offset += 1; + + return value; + + } + + nextUint16 () { + + var value = this.dataView.getUint16( this.offset, this.littleEndian ); + + this.offset += 2; + + return value; + + } + + nextUint32 () { + + var value = this.dataView.getUint32( this.offset, this.littleEndian ); + + this.offset += 4; + + return value; + + } + + nextUint64 () { + + // https://stackoverflow.com/questions/53103695/ + var left = this.dataView.getUint32( this.offset, this.littleEndian ); + var right = this.dataView.getUint32( this.offset + 4, this.littleEndian ); + var value = this.littleEndian ? left + ( 2 ** 32 * right ) : ( 2 ** 32 * left ) + right; + + if ( ! Number.isSafeInteger( value ) ) { + + console.warn( 'THREE.KTX2Loader: ' + value + ' exceeds MAX_SAFE_INTEGER. Precision may be lost.' ); + + } + + this.offset += 8; + + return value; + + } + + skip ( bytes ) { + + this.offset += bytes; + + return this; + + } + +} + +export { KTX2Loader }; diff --git a/examples/textures/compressed/sample_etc1s.ktx2 b/examples/textures/compressed/sample_etc1s.ktx2 new file mode 100644 index 00000000000000..39a1bd6c1afa3e Binary files /dev/null and b/examples/textures/compressed/sample_etc1s.ktx2 differ diff --git a/examples/textures/compressed/sample_uastc.ktx2 b/examples/textures/compressed/sample_uastc.ktx2 new file mode 100644 index 00000000000000..66fe5c96635491 Binary files /dev/null and b/examples/textures/compressed/sample_uastc.ktx2 differ diff --git a/examples/webgl_loader_texture_ktx2.html b/examples/webgl_loader_texture_ktx2.html new file mode 100644 index 00000000000000..d4aef2d833c1f4 --- /dev/null +++ b/examples/webgl_loader_texture_ktx2.html @@ -0,0 +1,119 @@ + + + + three.js webgl - KTX2 texture loader + + + + + + +
+ three.js - webgl - KTX2 texture loader
+ KTX2 with + Basis Universal GPU Texture Codec +
+ + + + + + +