Updated Draco to 1.1.0

The latest version of Draco brings a number of new compression
enhancements for even smaller models:
- Improved compression
  - Up to 40% better compression of normals
  - Up to 5% better compression for models with multiple attributes
- Faster decode speeds
  - 30% faster decoding for models with multiple attributes for lower compression levels 4 and below
    - Note: Decreases compression by 10%.
- Encoding of metadata to .obj (e.g. Draco can preserve material or sub-object names)
- Security fixes
This commit is contained in:
Ondrej Stava 2017-09-11 15:38:19 -07:00
parent 5da5579bc1
commit dc28e6a2ea
49 changed files with 853 additions and 299 deletions

View File

@ -49,6 +49,7 @@ if (ENABLE_MESH_COMPRESSION)
endif ()
endif ()
# Turn on more compiler warnings.
if (ENABLE_EXTRA_WARNINGS)
if (MSVC)
@ -534,6 +535,7 @@ set(draco_test_sources
"${draco_src_root}/core/symbol_coding_test.cc"
"${draco_src_root}/core/vector_d_test.cc"
"${draco_src_root}/io/obj_decoder_test.cc"
"${draco_src_root}/io/obj_encoder_test.cc"
"${draco_src_root}/io/ply_decoder_test.cc"
"${draco_src_root}/io/ply_reader_test.cc"
"${draco_src_root}/io/point_cloud_io_test.cc"
@ -565,12 +567,12 @@ if (EMSCRIPTEN)
require_compiler_flag("--llvm-lto 1" YES)
endif ()
require_compiler_flag("-s NO_FILESYSTEM=1" YES)
require_compiler_flag("-s ELIMINATE_DUPLICATE_FUNCTIONS=1" YES)
require_compiler_flag("-s EXPORTED_RUNTIME_METHODS=[]" YES)
require_compiler_flag("-s PRECISE_F32=1" YES)
if (ENABLE_WASM)
require_compiler_flag("-s WASM=1" YES)
require_compiler_flag("-s BINARYEN_IMPRECISE=1" YES)
else ()
require_compiler_flag("-s ELIMINATE_DUPLICATE_FUNCTIONS=1" YES)
endif ()
if (CMAKE_BUILD_TYPE STREQUAL "")
@ -588,14 +590,17 @@ if (EMSCRIPTEN)
execute_process(COMMAND ${PYTHON_EXECUTABLE}
$ENV{EMSCRIPTEN}/tools/webidl_binder.py
${draco_js_dec_idl}
${draco_build_dir}/glue_decoder
OUTPUT_FILE ${draco_build_dir}/glue_decoder.cpp)
${draco_build_dir}/glue_decoder)
execute_process(COMMAND ${PYTHON_EXECUTABLE}
$ENV{EMSCRIPTEN}/tools/webidl_binder.py
${draco_js_enc_idl}
${draco_build_dir}/glue_encoder
OUTPUT_FILE ${draco_build_dir}/glue_encoder.cpp)
${draco_build_dir}/glue_encoder)
if (NOT EXISTS "${draco_build_dir}/glue_decoder.cpp" OR
NOT EXISTS "${draco_build_dir}/glue_encoder.cpp")
message(FATAL_ERROR "Glue generation failed.")
endif ()
# Add a custom rule depending on the IDL to regenerate
# ${draco_build_dir}/glue_decoder.cpp as needed.

View File

@ -5,23 +5,17 @@
News
=======
### Version 1.0.0 release
The latest version of Draco brings many new enhancements to improve the
development experience:
* Stable API release
* Support for npm Javascript package management
* Javascript based encoder
* Generalized metadata for meshes and point clouds
* Now supporting material properties included along with encoded file
* Improved compression rates:
* 15% better compression on smaller models
* 40% better compression of normals
* Performance improvements (~10% faster encoding, decoding)
* Reduced GPU memory usage:
* Option to store decoded quantized attributes
* Support for triangle strip connectivity on decoded meshes
* iOS 9 Javascript decoder
* Bitstream specification now available
### Version 1.1.0 release
The latest version of Draco brings a number of new compression enhancements for
even smaller models:
* Improved compression
* Up to 40% better compression of normals
* Up to 5% better compression for models with multiple attributes
* Faster decode speeds
* 30% faster decoding for models with multiple attributes for lower compression levels 4 and below
* Note: Decreases compression by 10%.
* Encoding of metadata to .obj (e.g. Draco can preserve material or sub-object names)
* Security fixes
@ -54,7 +48,7 @@ _**Contents**_
* [CMake Build Configuration](#cmake-build-config)
* [Debugging and Optimization](#debugging-and-optimization)
* [Googletest Integration](#googletest-integration)
* [Javascript Decoder](#javascript-decoder)
* [Javascript Encoder/Decoder](#javascript-decoder)
* [Android Studio Project Integration](#android-studio-project-integration)
* [Usage](#usage)
* [Command Line Applications](#command-line-applications)

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,124 +1,125 @@
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(e,m,f){e!=Array.prototype&&e!=Object.prototype&&(e[m]=f.value)};$jscomp.getGlobal=function(e){return"undefined"!=typeof window&&window===e?e:"undefined"!=typeof global&&null!=global?global:e};$jscomp.global=$jscomp.getGlobal(this);
$jscomp.polyfill=function(e,m,f,z){if(m){f=$jscomp.global;e=e.split(".");for(z=0;z<e.length-1;z++){var h=e[z];h in f||(f[h]={});f=f[h]}e=e[e.length-1];z=f[e];m=m(z);m!=z&&null!=m&&$jscomp.defineProperty(f,e,{configurable:!0,writable:!0,value:m})}};$jscomp.polyfill("Math.imul",function(e){return e?e:function(e,f){e=Number(e);f=Number(f);var m=e&65535,h=f&65535;return m*h+((e>>>16&65535)*h+m*(f>>>16&65535)<<16>>>0)|0}},"es6","es3");
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(e,h,f){e!=Array.prototype&&e!=Object.prototype&&(e[h]=f.value)};$jscomp.getGlobal=function(e){return"undefined"!=typeof window&&window===e?e:"undefined"!=typeof global&&null!=global?global:e};$jscomp.global=$jscomp.getGlobal(this);
$jscomp.polyfill=function(e,h,f,z){if(h){f=$jscomp.global;e=e.split(".");for(z=0;z<e.length-1;z++){var k=e[z];k in f||(f[k]={});f=f[k]}e=e[e.length-1];z=f[e];h=h(z);h!=z&&null!=h&&$jscomp.defineProperty(f,e,{configurable:!0,writable:!0,value:h})}};$jscomp.polyfill("Math.imul",function(e){return e?e:function(e,f){e=Number(e);f=Number(f);var h=e&65535,k=f&65535;return h*k+((e>>>16&65535)*k+h*(f>>>16&65535)<<16>>>0)|0}},"es6","es3");
$jscomp.polyfill("Math.clz32",function(e){return e?e:function(e){e=Number(e)>>>0;if(0===e)return 32;var f=0;0===(e&4294901760)&&(e<<=16,f+=16);0===(e&4278190080)&&(e<<=8,f+=8);0===(e&4026531840)&&(e<<=4,f+=4);0===(e&3221225472)&&(e<<=2,f+=2);0===(e&2147483648)&&f++;return f}},"es6","es3");$jscomp.polyfill("Math.trunc",function(e){return e?e:function(e){e=Number(e);if(isNaN(e)||Infinity===e||-Infinity===e||0===e)return e;var f=Math.floor(Math.abs(e));return 0>e?-f:f}},"es6","es3");
$jscomp.SYMBOL_PREFIX="jscomp_symbol_";$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.Symbol=function(){var e=0;return function(m){return $jscomp.SYMBOL_PREFIX+(m||"")+e++}}();
$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var e=$jscomp.global.Symbol.iterator;e||(e=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[e]&&$jscomp.defineProperty(Array.prototype,e,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(e){var m=0;return $jscomp.iteratorPrototype(function(){return m<e.length?{done:!1,value:e[m++]}:{done:!0}})};
$jscomp.iteratorPrototype=function(e){$jscomp.initSymbolIterator();e={next:e};e[$jscomp.global.Symbol.iterator]=function(){return this};return e};$jscomp.makeIterator=function(e){$jscomp.initSymbolIterator();var m=e[Symbol.iterator];return m?m.call(e):$jscomp.arrayIterator(e)};$jscomp.FORCE_POLYFILL_PROMISE=!1;
$jscomp.polyfill("Promise",function(e){function m(){this.batch_=null}function f(e){return e instanceof h?e:new h(function(t,f){t(e)})}if(e&&!$jscomp.FORCE_POLYFILL_PROMISE)return e;m.prototype.asyncExecute=function(e){null==this.batch_&&(this.batch_=[],this.asyncExecuteBatch_());this.batch_.push(e);return this};m.prototype.asyncExecuteBatch_=function(){var e=this;this.asyncExecuteFunction(function(){e.executeBatch_()})};var z=$jscomp.global.setTimeout;m.prototype.asyncExecuteFunction=function(e){z(e,
0)};m.prototype.executeBatch_=function(){for(;this.batch_&&this.batch_.length;){var e=this.batch_;this.batch_=[];for(var f=0;f<e.length;++f){var h=e[f];delete e[f];try{h()}catch(qa){this.asyncThrow_(qa)}}}this.batch_=null};m.prototype.asyncThrow_=function(e){this.asyncExecuteFunction(function(){throw e;})};var h=function(e){this.state_=0;this.result_=void 0;this.onSettledCallbacks_=[];var f=this.createResolveAndReject_();try{e(f.resolve,f.reject)}catch(ia){f.reject(ia)}};h.prototype.createResolveAndReject_=
function(){function e(e){return function(t){h||(h=!0,e.call(f,t))}}var f=this,h=!1;return{resolve:e(this.resolveTo_),reject:e(this.reject_)}};h.prototype.resolveTo_=function(e){if(e===this)this.reject_(new TypeError("A Promise cannot resolve to itself"));else if(e instanceof h)this.settleSameAsPromise_(e);else{a:switch(typeof e){case "object":var f=null!=e;break a;case "function":f=!0;break a;default:f=!1}f?this.resolveToNonPromiseObj_(e):this.fulfill_(e)}};h.prototype.resolveToNonPromiseObj_=function(e){var f=
void 0;try{f=e.then}catch(ia){this.reject_(ia);return}"function"==typeof f?this.settleSameAsThenable_(f,e):this.fulfill_(e)};h.prototype.reject_=function(e){this.settle_(2,e)};h.prototype.fulfill_=function(e){this.settle_(1,e)};h.prototype.settle_=function(e,f){if(0!=this.state_)throw Error("Cannot settle("+e+", "+f|"): Promise already settled in state"+this.state_);this.state_=e;this.result_=f;this.executeOnSettledCallbacks_()};h.prototype.executeOnSettledCallbacks_=function(){if(null!=this.onSettledCallbacks_){for(var e=
this.onSettledCallbacks_,f=0;f<e.length;++f)e[f].call(),e[f]=null;this.onSettledCallbacks_=null}};var R=new m;h.prototype.settleSameAsPromise_=function(e){var f=this.createResolveAndReject_();e.callWhenSettled_(f.resolve,f.reject)};h.prototype.settleSameAsThenable_=function(e,f){var h=this.createResolveAndReject_();try{e.call(f,h.resolve,h.reject)}catch(qa){h.reject(qa)}};h.prototype.then=function(e,f){function m(e,f){return"function"==typeof e?function(f){try{t(e(f))}catch(ra){ja(ra)}}:f}var t,ja,
z=new h(function(e,f){t=e;ja=f});this.callWhenSettled_(m(e,t),m(f,ja));return z};h.prototype.catch=function(e){return this.then(void 0,e)};h.prototype.callWhenSettled_=function(e,f){function h(){switch(m.state_){case 1:e(m.result_);break;case 2:f(m.result_);break;default:throw Error("Unexpected state: "+m.state_);}}var m=this;null==this.onSettledCallbacks_?R.asyncExecute(h):this.onSettledCallbacks_.push(function(){R.asyncExecute(h)})};h.resolve=f;h.reject=function(e){return new h(function(f,h){h(e)})};
h.race=function(e){return new h(function(h,m){for(var t=$jscomp.makeIterator(e),z=t.next();!z.done;z=t.next())f(z.value).callWhenSettled_(h,m)})};h.all=function(e){var m=$jscomp.makeIterator(e),t=m.next();return t.done?f([]):new h(function(e,h){function z(f){return function(h){ba[f]=h;R--;0==R&&e(ba)}}var ba=[],R=0;do ba.push(void 0),R++,f(t.value).callWhenSettled_(z(ba.length-1),h),t=m.next();while(!t.done)})};return h},"es6","es3");
var DracoDecoderModule=function(e){function m(a){eval.call(null,a)}function f(a,b){a||M("Assertion failed: "+b)}function z(d){var b=a["_"+d];if(!b)try{b=eval("_"+d)}catch(c){}f(b,"Cannot call unknown function "+d+" (perhaps LLVM optimizations or closure removed it?)");return b}function h(a,b,c){b=b||"i8";"*"===b.charAt(b.length-1)&&(b="i32");switch(b){case "i1":return N[a>>0];case "i8":return N[a>>0];case "i16":return sa[a>>1];case "i32":return u[a>>2];case "i64":return u[a>>2];case "float":return ya[a>>
2];case "double":return za[a>>3];default:M("invalid type for setValue: "+b)}return null}function R(a,b,c,g){if("number"===typeof a){var d=!0;var e=a}else d=!1,e=a.length;var S="string"===typeof b?b:null;c=4==c?g:["function"===typeof la?la:n.staticAlloc,n.stackAlloc,n.staticAlloc,n.dynamicAlloc][void 0===c?2:c](Math.max(e,S?1:b.length));if(d){g=c;f(0==(c&3));for(a=c+(e&-4);g<a;g+=4)u[g>>2]=0;for(a=c+e;g<a;)N[g++>>0]=0;return c}if("i8"===S)return a.subarray||a.slice?G.set(a,c):G.set(new Uint8Array(a),
c),c;g=0;for(var h,m;g<e;){var k=a[g];"function"===typeof k&&(k=n.getFunctionIndex(k));d=S||b[g];if(0===d)g++;else{"i64"==d&&(d="i32");var l=c+g,ea=d;ea=ea||"i8";"*"===ea.charAt(ea.length-1)&&(ea="i32");switch(ea){case "i1":N[l>>0]=k;break;case "i8":N[l>>0]=k;break;case "i16":sa[l>>1]=k;break;case "i32":u[l>>2]=k;break;case "i64":tempI64=[k>>>0,(tempDouble=k,1<=+qb(tempDouble)?0<tempDouble?(rb(+sb(tempDouble/4294967296),4294967295)|0)>>>0:~~+tb((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)];
u[l>>2]=tempI64[0];u[l+4>>2]=tempI64[1];break;case "float":ya[l>>2]=k;break;case "double":za[l>>3]=k;break;default:M("invalid type for setValue: "+ea)}m!==d&&(h=n.getNativeTypeSize(d),m=d);g+=h}}return c}function t(d,b){if(0===b||!d)return"";for(var c=0,g,e=0;;){g=G[d+e>>0];c|=g;if(0==g&&!b)break;e++;if(b&&e==b)break}b||(b=e);g="";if(128>c){for(;0<b;)c=String.fromCharCode.apply(String,G.subarray(d,d+Math.min(b,1024))),g=g?g+c:c,d+=1024,b-=1024;return g}return a.UTF8ToString(d)}function Ea(a,b,c,g){if(!(0<
$jscomp.SYMBOL_PREFIX="jscomp_symbol_";$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(e){return $jscomp.SYMBOL_PREFIX+(e||"")+$jscomp.symbolCounter_++};
$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var e=$jscomp.global.Symbol.iterator;e||(e=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[e]&&$jscomp.defineProperty(Array.prototype,e,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(e){var h=0;return $jscomp.iteratorPrototype(function(){return h<e.length?{done:!1,value:e[h++]}:{done:!0}})};
$jscomp.iteratorPrototype=function(e){$jscomp.initSymbolIterator();e={next:e};e[$jscomp.global.Symbol.iterator]=function(){return this};return e};$jscomp.makeIterator=function(e){$jscomp.initSymbolIterator();var h=e[Symbol.iterator];return h?h.call(e):$jscomp.arrayIterator(e)};$jscomp.FORCE_POLYFILL_PROMISE=!1;
$jscomp.polyfill("Promise",function(e){function h(){this.batch_=null}function f(e){return e instanceof k?e:new k(function(t,f){t(e)})}if(e&&!$jscomp.FORCE_POLYFILL_PROMISE)return e;h.prototype.asyncExecute=function(e){null==this.batch_&&(this.batch_=[],this.asyncExecuteBatch_());this.batch_.push(e);return this};h.prototype.asyncExecuteBatch_=function(){var e=this;this.asyncExecuteFunction(function(){e.executeBatch_()})};var z=$jscomp.global.setTimeout;h.prototype.asyncExecuteFunction=function(e){z(e,
0)};h.prototype.executeBatch_=function(){for(;this.batch_&&this.batch_.length;){var e=this.batch_;this.batch_=[];for(var f=0;f<e.length;++f){var k=e[f];delete e[f];try{k()}catch(pa){this.asyncThrow_(pa)}}}this.batch_=null};h.prototype.asyncThrow_=function(e){this.asyncExecuteFunction(function(){throw e;})};var k=function(e){this.state_=0;this.result_=void 0;this.onSettledCallbacks_=[];var f=this.createResolveAndReject_();try{e(f.resolve,f.reject)}catch(ha){f.reject(ha)}};k.prototype.createResolveAndReject_=
function(){function e(e){return function(t){k||(k=!0,e.call(f,t))}}var f=this,k=!1;return{resolve:e(this.resolveTo_),reject:e(this.reject_)}};k.prototype.resolveTo_=function(e){if(e===this)this.reject_(new TypeError("A Promise cannot resolve to itself"));else if(e instanceof k)this.settleSameAsPromise_(e);else{a:switch(typeof e){case "object":var f=null!=e;break a;case "function":f=!0;break a;default:f=!1}f?this.resolveToNonPromiseObj_(e):this.fulfill_(e)}};k.prototype.resolveToNonPromiseObj_=function(e){var f=
void 0;try{f=e.then}catch(ha){this.reject_(ha);return}"function"==typeof f?this.settleSameAsThenable_(f,e):this.fulfill_(e)};k.prototype.reject_=function(e){this.settle_(2,e)};k.prototype.fulfill_=function(e){this.settle_(1,e)};k.prototype.settle_=function(e,f){if(0!=this.state_)throw Error("Cannot settle("+e+", "+f|"): Promise already settled in state"+this.state_);this.state_=e;this.result_=f;this.executeOnSettledCallbacks_()};k.prototype.executeOnSettledCallbacks_=function(){if(null!=this.onSettledCallbacks_){for(var e=
this.onSettledCallbacks_,f=0;f<e.length;++f)e[f].call(),e[f]=null;this.onSettledCallbacks_=null}};var R=new h;k.prototype.settleSameAsPromise_=function(e){var f=this.createResolveAndReject_();e.callWhenSettled_(f.resolve,f.reject)};k.prototype.settleSameAsThenable_=function(e,f){var k=this.createResolveAndReject_();try{e.call(f,k.resolve,k.reject)}catch(pa){k.reject(pa)}};k.prototype.then=function(e,f){function h(e,f){return"function"==typeof e?function(f){try{t(e(f))}catch(qa){ia(qa)}}:f}var t,ia,
z=new k(function(e,f){t=e;ia=f});this.callWhenSettled_(h(e,t),h(f,ia));return z};k.prototype.catch=function(e){return this.then(void 0,e)};k.prototype.callWhenSettled_=function(e,f){function k(){switch(h.state_){case 1:e(h.result_);break;case 2:f(h.result_);break;default:throw Error("Unexpected state: "+h.state_);}}var h=this;null==this.onSettledCallbacks_?R.asyncExecute(k):this.onSettledCallbacks_.push(function(){R.asyncExecute(k)})};k.resolve=f;k.reject=function(e){return new k(function(f,k){k(e)})};
k.race=function(e){return new k(function(k,h){for(var t=$jscomp.makeIterator(e),z=t.next();!z.done;z=t.next())f(z.value).callWhenSettled_(k,h)})};k.all=function(e){var h=$jscomp.makeIterator(e),t=h.next();return t.done?f([]):new k(function(e,k){function z(f){return function(k){ba[f]=k;R--;0==R&&e(ba)}}var ba=[],R=0;do ba.push(void 0),R++,f(t.value).callWhenSettled_(z(ba.length-1),k),t=h.next();while(!t.done)})};return k},"es6","es3");
var DracoDecoderModule=function(e){function h(a){eval.call(null,a)}function f(a,b){a||M("Assertion failed: "+b)}function z(d){var b=a["_"+d];if(!b)try{b=eval("_"+d)}catch(c){}f(b,"Cannot call unknown function "+d+" (perhaps LLVM optimizations or closure removed it?)");return b}function k(a,b,c){b=b||"i8";"*"===b.charAt(b.length-1)&&(b="i32");switch(b){case "i1":return N[a>>0];case "i8":return N[a>>0];case "i16":return ra[a>>1];case "i32":return u[a>>2];case "i64":return u[a>>2];case "float":return xa[a>>
2];case "double":return ya[a>>3];default:M("invalid type for setValue: "+b)}return null}function R(a,b,c,g){if("number"===typeof a){var d=!0;var e=a}else d=!1,e=a.length;var S="string"===typeof b?b:null;c=4==c?g:["function"===typeof ka?ka:n.staticAlloc,n.stackAlloc,n.staticAlloc,n.dynamicAlloc][void 0===c?2:c](Math.max(e,S?1:b.length));if(d){g=c;f(0==(c&3));for(a=c+(e&-4);g<a;g+=4)u[g>>2]=0;for(a=c+e;g<a;)N[g++>>0]=0;return c}if("i8"===S)return a.subarray||a.slice?G.set(a,c):G.set(new Uint8Array(a),
c),c;g=0;for(var k,m;g<e;){var h=a[g];"function"===typeof h&&(h=n.getFunctionIndex(h));d=S||b[g];if(0===d)g++;else{"i64"==d&&(d="i32");var l=c+g,p=d;p=p||"i8";"*"===p.charAt(p.length-1)&&(p="i32");switch(p){case "i1":N[l>>0]=h;break;case "i8":N[l>>0]=h;break;case "i16":ra[l>>1]=h;break;case "i32":u[l>>2]=h;break;case "i64":tempI64=[h>>>0,(tempDouble=h,1<=+pb(tempDouble)?0<tempDouble?(qb(+rb(tempDouble/4294967296),4294967295)|0)>>>0:~~+sb((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)];u[l>>2]=
tempI64[0];u[l+4>>2]=tempI64[1];break;case "float":xa[l>>2]=h;break;case "double":ya[l>>3]=h;break;default:M("invalid type for setValue: "+p)}m!==d&&(k=n.getNativeTypeSize(d),m=d);g+=k}}return c}function t(d,b){if(0===b||!d)return"";for(var c=0,g,e=0;;){g=G[d+e>>0];c|=g;if(0==g&&!b)break;e++;if(b&&e==b)break}b||(b=e);g="";if(128>c){for(;0<b;)c=String.fromCharCode.apply(String,G.subarray(d,d+Math.min(b,1024))),g=g?g+c:c,d+=1024,b-=1024;return g}return a.UTF8ToString(d)}function Da(a,b,c,g){if(!(0<
g))return 0;var d=c;g=c+g-1;for(var e=0;e<a.length;++e){var f=a.charCodeAt(e);55296<=f&&57343>=f&&(f=65536+((f&1023)<<10)|a.charCodeAt(++e)&1023);if(127>=f){if(c>=g)break;b[c++]=f}else{if(2047>=f){if(c+1>=g)break;b[c++]=192|f>>6}else{if(65535>=f){if(c+2>=g)break;b[c++]=224|f>>12}else{if(2097151>=f){if(c+3>=g)break;b[c++]=240|f>>18}else{if(67108863>=f){if(c+4>=g)break;b[c++]=248|f>>24}else{if(c+5>=g)break;b[c++]=252|f>>30;b[c++]=128|f>>24&63}b[c++]=128|f>>18&63}b[c++]=128|f>>12&63}b[c++]=128|f>>6&
63}b[c++]=128|f&63}}b[c]=0;return c-d}function ia(a){for(var b=0,d=0;d<a.length;++d){var g=a.charCodeAt(d);55296<=g&&57343>=g&&(g=65536+((g&1023)<<10)|a.charCodeAt(++d)&1023);127>=g?++b:b=2047>=g?b+2:65535>=g?b+3:2097151>=g?b+4:67108863>=g?b+5:b+6}return b}function qa(d){return d.replace(/__Z[\w\d_]+/g,function(b){a:{var d=a.___cxa_demangle||a.__cxa_demangle;if(d)try{var g=b.substr(1),e=ia(g)+1;var f=la(e);Ea(g,G,f,e);var k=la(4);var l=d(f,0,0,k);if(0===h(k,"i32")&&l){var m=t(l);break a}}catch(xd){}finally{f&&
Ia(f),k&&Ia(k),l&&Ia(l)}else n.warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");m=b}return b===m?b:b+" ["+m+"]"})}function ja(){a:{var d=Error();if(!d.stack){try{throw Error(0);}catch(b){d=b}if(!d.stack){d="(no stack trace available)";break a}}d=d.stack.toString()}a.extraStackTrace&&(d+="\n"+a.extraStackTrace());return qa(d)}function Fa(a,b){0<a%b&&(a+=b-a%b);return a}function ba(){a.HEAP8=N=new Int8Array(H);a.HEAP16=sa=new Int16Array(H);a.HEAP32=u=new Int32Array(H);
a.HEAPU8=G=new Uint8Array(H);a.HEAPU16=Wa=new Uint16Array(H);a.HEAPU32=Xa=new Uint32Array(H);a.HEAPF32=ya=new Float32Array(H);a.HEAPF64=za=new Float64Array(H)}function Va(){var d=a.usingWasm?Ja:Ya,b=2147483648-d;if(u[X>>2]>b)return!1;var c=x;for(x=Math.max(x,ub);x<u[X>>2];)x=536870912>=x?Fa(2*x,d):Math.min(Fa((3*x+2147483648)/4,d),b);d=a.reallocBuffer(x);if(!d||d.byteLength!=x)return x=c,!1;a.buffer=H=d;ba();return!0}function ka(d){for(;0<d.length;){var b=d.shift();if("function"==typeof b)b();else{var c=
b.func;"number"===typeof c?void 0===b.arg?a.dynCall_v(c):a.dynCall_vi(c,b.arg):c(void 0===b.arg?null:b.arg)}}}function ra(a,b,c){c=0<c?c:ia(a)+1;c=Array(c);a=Ea(a,c,0,c.length);b&&(c.length=a);return c}function Za(d){fa++;a.monitorRunDependencies&&a.monitorRunDependencies(fa)}function $a(d){fa--;a.monitorRunDependencies&&a.monitorRunDependencies(fa);0==fa&&(null!==Ka&&(clearInterval(Ka),Ka=null),ta&&(d=ta,ta=null,d()))}function ma(){return!!ma.uncaught_exception}function ua(){var d=C.last;if(!d)return(n.setTempRet0(0),
0)|0;var b=C.infos[d],c=b.type;if(!c)return(n.setTempRet0(0),d)|0;var g=Array.prototype.slice.call(arguments);a.___cxa_is_pointer_type(c);ua.buffer||(ua.buffer=la(4));u[ua.buffer>>2]=d;d=ua.buffer;for(var e=0;e<g.length;e++)if(g[e]&&a.___cxa_can_catch(g[e],c,d))return d=u[d>>2],b.adjusted=d,(n.setTempRet0(g[e]),d)|0;d=u[d>>2];return(n.setTempRet0(c),d)|0}function va(d,b){va.seen||(va.seen={});d in va.seen||(a.dynCall_v(b),va.seen[d]=1)}function ca(d,b){r.varargs=b;try{var c=r.get(),g=r.get(),e=r.get();
d=0;ca.buffer||(ca.buffers=[null,[],[]],ca.printChar=function(b,d){var c=ca.buffers[b];f(c);if(0===d||10===d){b=1===b?a.print:a.printErr;a:{for(var e=d=0;c[e];)++e;if(16<e-d&&c.subarray&&ab)d=ab.decode(c.subarray(d,e));else for(e="";;){var g=c[d++];if(!g){d=e;break a}if(g&128){var h=c[d++]&63;if(192==(g&224))e+=String.fromCharCode((g&31)<<6|h);else{var k=c[d++]&63;if(224==(g&240))g=(g&15)<<12|h<<6|k;else{var l=c[d++]&63;if(240==(g&248))g=(g&7)<<18|h<<12|k<<6|l;else{var A=c[d++]&63;if(248==(g&252))g=
(g&3)<<24|h<<18|k<<12|l<<6|A;else{var m=c[d++]&63;g=(g&1)<<30|h<<24|k<<18|l<<12|A<<6|m}}}65536>g?e+=String.fromCharCode(g):(g-=65536,e+=String.fromCharCode(55296|g>>10,56320|g&1023))}}else e+=String.fromCharCode(g)}}b(d);c.length=0}else c.push(d)});for(b=0;b<e;b++){for(var k=u[g+8*b>>2],h=u[g+(8*b+4)>>2],l=0;l<h;l++)ca.printChar(c,G[k+l]);d+=h}return d}catch(Ha){return"undefined"!==typeof FS&&Ha instanceof FS.ErrnoError||M(Ha),-Ha.errno}}function na(a){this.name="ExitStatus";this.message="Program terminated with exit("+
a+")";this.status=a}function La(d){function b(){if(!a.calledRun&&(a.calledRun=!0,!oa)){Aa||(Aa=!0,ka(Ma));ka(bb);if(a.onRuntimeInitialized)a.onRuntimeInitialized();a._main&&cb&&a.callMain(d);if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;)db.unshift(a.postRun.shift());ka(db)}}d=d||a.arguments;null===eb&&(eb=Date.now());if(!(0<fa)){if(a.preRun)for("function"==typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)fb.unshift(a.preRun.shift());ka(fb);0<fa||a.calledRun||
(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);b()},1)):b())}}function gb(d,b){if(!b||!a.noExitRuntime){if(!a.noExitRuntime&&(oa=!0,T=vb,ka(hb),a.onExit))a.onExit(d);pa&&process.exit(d);a.quit(d,new na(d))}}function M(d){if(a.onAbort)a.onAbort(d);void 0!==d?(a.print(d),a.printErr(d),d=JSON.stringify(d)):d="";oa=!0;var b="abort("+d+") at "+ja()+"\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";ib&&
ib.forEach(function(a){b=a(b,d)});throw b;}function v(){}function E(a){return(a||v).__cache__}function Y(a,b){var d=E(b),g=d[a];if(g)return g;g=Object.create((b||v).prototype);g.ptr=a;return d[a]=g}function Z(a){if("string"===typeof a){a=ra(a);var b=k.alloc(a,N);k.copy(a,N,b);return b}return a}function D(){throw"cannot construct a Status, no constructor in IDL";}function I(){this.ptr=wb();E(I)[this.ptr]=this}function J(){this.ptr=xb();E(J)[this.ptr]=this}function p(){this.ptr=yb();E(p)[this.ptr]=
this}function O(){this.ptr=zb();E(O)[this.ptr]=this}function B(){this.ptr=Ab();E(B)[this.ptr]=this}function q(){this.ptr=Bb();E(q)[this.ptr]=this}function K(){this.ptr=Cb();E(K)[this.ptr]=this}function V(){this.ptr=Db();E(V)[this.ptr]=this}function P(){this.ptr=Eb();E(P)[this.ptr]=this}function l(){this.ptr=Fb();E(l)[this.ptr]=this}function F(){this.ptr=Gb();E(F)[this.ptr]=this}function aa(){throw"cannot construct a VoidPtr, no constructor in IDL";}function L(){this.ptr=Hb();E(L)[this.ptr]=this}function Q(){this.ptr=
Ib();E(Q)[this.ptr]=this}var a=e=e||{},jb=!1,kb=!1;a.onRuntimeInitialized=function(){jb=!0;if(kb&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.onModuleParsed=function(){kb=!0;if(jb&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.isVersionSupported=function(a){if("string"!==typeof a)return!1;a=a.split(".");return 2>a.length||3<a.length?!1:1==a[0]&&0==a[1]?!0:0!=a[0]||10<a[1]?!1:!0};a||(a=("undefined"!==typeof e?e:null)||{});var wa={},da;for(da in a)a.hasOwnProperty(da)&&
(wa[da]=a[da]);var xa=!1,ha=!1,pa=!1,Ba=!1;if(a.ENVIRONMENT)if("WEB"===a.ENVIRONMENT)xa=!0;else if("WORKER"===a.ENVIRONMENT)ha=!0;else if("NODE"===a.ENVIRONMENT)pa=!0;else if("SHELL"===a.ENVIRONMENT)Ba=!0;else throw Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");else xa="object"===typeof window,ha="function"===typeof importScripts,pa="object"===typeof process&&"function"===typeof require&&!xa&&!ha,Ba=!xa&&!pa&&!ha;if(pa){a.print||(a.print=
console.log);a.printErr||(a.printErr=console.warn);var Na,Oa;a.read=function(a,b){Na||(Na=require("fs"));Oa||(Oa=require("path"));a=Oa.normalize(a);a=Na.readFileSync(a);return b?a:a.toString()};a.readBinary=function(d){d=a.read(d,!0);d.buffer||(d=new Uint8Array(d));f(d.buffer);return d};a.load=function(a){m(read(a))};a.thisProgram||(a.thisProgram=1<process.argv.length?process.argv[1].replace(/\\/g,"/"):"unknown-program");a.arguments=process.argv.slice(2);"undefined"!==typeof module&&(module.exports=
a);process.on("uncaughtException",function(a){if(!(a instanceof na))throw a;});a.inspect=function(){return"[Emscripten Module object]"}}else if(Ba)a.print||(a.print=print),"undefined"!=typeof printErr&&(a.printErr=printErr),a.read="undefined"!=typeof read?read:function(){throw"no read() available";},a.readBinary=function(a){if("function"===typeof readbuffer)return new Uint8Array(readbuffer(a));a=read(a,"binary");f("object"===typeof a);return a},"undefined"!=typeof scriptArgs?a.arguments=scriptArgs:
"undefined"!=typeof arguments&&(a.arguments=arguments),"function"===typeof quit&&(a.quit=function(a,b){quit(a)});else if(xa||ha)a.read=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},ha&&(a.readBinary=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),a.readAsync=function(a,b,c){var d=new XMLHttpRequest;d.open("GET",a,!0);d.responseType="arraybuffer";d.onload=function(){200==
d.status||0==d.status&&d.response?b(d.response):c()};d.onerror=c;d.send(null)},"undefined"!=typeof arguments&&(a.arguments=arguments),"undefined"!==typeof console?(a.print||(a.print=function(a){console.log(a)}),a.printErr||(a.printErr=function(a){console.warn(a)})):a.print||(a.print=function(a){}),ha&&(a.load=importScripts),"undefined"===typeof a.setWindowTitle&&(a.setWindowTitle=function(a){document.title=a});else throw"Unknown runtime environment. Where are we?";!a.load&&a.read&&(a.load=function(d){m(a.read(d))});
a.print||(a.print=function(){});a.printErr||(a.printErr=a.print);a.arguments||(a.arguments=[]);a.thisProgram||(a.thisProgram="./this.program");a.quit||(a.quit=function(a,b){throw b;});a.print=a.print;a.printErr=a.printErr;a.preRun=[];a.postRun=[];for(da in wa)wa.hasOwnProperty(da)&&(a[da]=wa[da]);wa=void 0;var n={setTempRet0:function(a){return tempRet0=a},getTempRet0:function(){return tempRet0},stackSave:function(){return T},stackRestore:function(a){T=a},getNativeTypeSize:function(a){switch(a){case "i1":case "i8":return 1;
63}b[c++]=128|f&63}}b[c]=0;return c-d}function ha(a){for(var b=0,d=0;d<a.length;++d){var g=a.charCodeAt(d);55296<=g&&57343>=g&&(g=65536+((g&1023)<<10)|a.charCodeAt(++d)&1023);127>=g?++b:b=2047>=g?b+2:65535>=g?b+3:2097151>=g?b+4:67108863>=g?b+5:b+6}return b}function pa(d){return d.replace(/__Z[\w\d_]+/g,function(b){a:{var d=a.___cxa_demangle||a.__cxa_demangle;if(d)try{var g=b.substr(1),e=ha(g)+1;var f=ka(e);Da(g,G,f,e);var h=ka(4);var l=d(f,0,0,h);if(0===k(h,"i32")&&l){var m=t(l);break a}}catch(xd){}finally{f&&
Ha(f),h&&Ha(h),l&&Ha(l)}else n.warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");m=b}return b===m?b:b+" ["+m+"]"})}function ia(){a:{var d=Error();if(!d.stack){try{throw Error(0);}catch(b){d=b}if(!d.stack){d="(no stack trace available)";break a}}d=d.stack.toString()}a.extraStackTrace&&(d+="\n"+a.extraStackTrace());return pa(d)}function Ea(a,b){0<a%b&&(a+=b-a%b);return a}function ba(){a.HEAP8=N=new Int8Array(H);a.HEAP16=ra=new Int16Array(H);a.HEAP32=u=new Int32Array(H);
a.HEAPU8=G=new Uint8Array(H);a.HEAPU16=Va=new Uint16Array(H);a.HEAPU32=Wa=new Uint32Array(H);a.HEAPF32=xa=new Float32Array(H);a.HEAPF64=ya=new Float64Array(H)}function Ua(){var d=a.usingWasm?Ia:Xa,b=2147483648-d;if(u[Y>>2]>b)return!1;var c=x;for(x=Math.max(x,tb);x<u[Y>>2];)x=536870912>=x?Ea(2*x,d):Math.min(Ea((3*x+2147483648)/4,d),b);d=a.reallocBuffer(x);if(!d||d.byteLength!=x)return x=c,!1;a.buffer=H=d;ba();return!0}function ja(d){for(;0<d.length;){var b=d.shift();if("function"==typeof b)b();else{var c=
b.func;"number"===typeof c?void 0===b.arg?a.dynCall_v(c):a.dynCall_vi(c,b.arg):c(void 0===b.arg?null:b.arg)}}}function qa(a,b,c){c=0<c?c:ha(a)+1;c=Array(c);a=Da(a,c,0,c.length);b&&(c.length=a);return c}function Ya(d){ea++;a.monitorRunDependencies&&a.monitorRunDependencies(ea)}function Za(d){ea--;a.monitorRunDependencies&&a.monitorRunDependencies(ea);0==ea&&(null!==Ja&&(clearInterval(Ja),Ja=null),sa&&(d=sa,sa=null,d()))}function la(){return!!la.uncaught_exception}function ta(){var d=C.last;if(!d)return(n.setTempRet0(0),
0)|0;var b=C.infos[d],c=b.type;if(!c)return(n.setTempRet0(0),d)|0;var g=Array.prototype.slice.call(arguments);a.___cxa_is_pointer_type(c);ta.buffer||(ta.buffer=ka(4));u[ta.buffer>>2]=d;d=ta.buffer;for(var e=0;e<g.length;e++)if(g[e]&&a.___cxa_can_catch(g[e],c,d))return d=u[d>>2],b.adjusted=d,(n.setTempRet0(g[e]),d)|0;d=u[d>>2];return(n.setTempRet0(c),d)|0}function ua(d,b){ua.seen||(ua.seen={});d in ua.seen||(a.dynCall_v(b),ua.seen[d]=1)}function ca(d,b){r.varargs=b;try{var c=r.get(),g=r.get(),e=r.get();
d=0;ca.buffer||(ca.buffers=[null,[],[]],ca.printChar=function(b,d){var c=ca.buffers[b];f(c);if(0===d||10===d){b=1===b?a.print:a.printErr;a:{for(var g=d=0;c[g];)++g;if(16<g-d&&c.subarray&&$a)d=$a.decode(c.subarray(d,g));else for(g="";;){var e=c[d++];if(!e){d=g;break a}if(e&128){var h=c[d++]&63;if(192==(e&224))g+=String.fromCharCode((e&31)<<6|h);else{var k=c[d++]&63;if(224==(e&240))e=(e&15)<<12|h<<6|k;else{var l=c[d++]&63;if(240==(e&248))e=(e&7)<<18|h<<12|k<<6|l;else{var A=c[d++]&63;if(248==(e&252))e=
(e&3)<<24|h<<18|k<<12|l<<6|A;else{var m=c[d++]&63;e=(e&1)<<30|h<<24|k<<18|l<<12|A<<6|m}}}65536>e?g+=String.fromCharCode(e):(e-=65536,g+=String.fromCharCode(55296|e>>10,56320|e&1023))}}else g+=String.fromCharCode(e)}}b(d);c.length=0}else c.push(d)});for(b=0;b<e;b++){for(var h=u[g+8*b>>2],k=u[g+(8*b+4)>>2],l=0;l<k;l++)ca.printChar(c,G[h+l]);d+=k}return d}catch(Ga){return"undefined"!==typeof FS&&Ga instanceof FS.ErrnoError||M(Ga),-Ga.errno}}function ma(a){this.name="ExitStatus";this.message="Program terminated with exit("+
a+")";this.status=a}function Ka(d){function b(){if(!a.calledRun&&(a.calledRun=!0,!na)){za||(za=!0,ja(La));ja(ab);if(a.onRuntimeInitialized)a.onRuntimeInitialized();a._main&&bb&&a.callMain(d);if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;)cb.unshift(a.postRun.shift());ja(cb)}}d=d||a.arguments;null===db&&(db=Date.now());if(!(0<ea)){if(a.preRun)for("function"==typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)eb.unshift(a.preRun.shift());ja(eb);0<ea||a.calledRun||
(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);b()},1)):b())}}function fb(d,b){if(!b||!a.noExitRuntime){if(!a.noExitRuntime&&(na=!0,T=ub,ja(gb),a.onExit))a.onExit(d);oa&&process.exit(d);a.quit(d,new ma(d))}}function M(d){if(a.onAbort)a.onAbort(d);void 0!==d?(a.print(d),a.printErr(d),d=JSON.stringify(d)):d="";na=!0;var b="abort("+d+") at "+ia()+"\nIf this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.";hb&&
hb.forEach(function(a){b=a(b,d)});throw b;}function v(){}function E(a){return(a||v).__cache__}function V(a,b){var d=E(b),e=d[a];if(e)return e;e=Object.create((b||v).prototype);e.ptr=a;return d[a]=e}function Z(a){if("string"===typeof a){a=qa(a);var b=l.alloc(a,N);l.copy(a,N,b);return b}return a}function D(){throw"cannot construct a Status, no constructor in IDL";}function I(){this.ptr=vb();E(I)[this.ptr]=this}function J(){this.ptr=wb();E(J)[this.ptr]=this}function p(){this.ptr=xb();E(p)[this.ptr]=
this}function O(){this.ptr=yb();E(O)[this.ptr]=this}function B(){this.ptr=zb();E(B)[this.ptr]=this}function q(){this.ptr=Ab();E(q)[this.ptr]=this}function K(){this.ptr=Bb();E(K)[this.ptr]=this}function W(){this.ptr=Cb();E(W)[this.ptr]=this}function P(){this.ptr=Db();E(P)[this.ptr]=this}function m(){this.ptr=Eb();E(m)[this.ptr]=this}function F(){this.ptr=Fb();E(F)[this.ptr]=this}function aa(){throw"cannot construct a VoidPtr, no constructor in IDL";}function L(){this.ptr=Gb();E(L)[this.ptr]=this}function Q(){this.ptr=
Hb();E(Q)[this.ptr]=this}var a=e=e||{},ib=!1,jb=!1;a.onRuntimeInitialized=function(){ib=!0;if(jb&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.onModuleParsed=function(){jb=!0;if(ib&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.isVersionSupported=function(a){if("string"!==typeof a)return!1;a=a.split(".");return 2>a.length||3<a.length?!1:1==a[0]&&0==a[1]?!0:0!=a[0]||10<a[1]?!1:!0};a||(a=("undefined"!==typeof e?e:null)||{});var va={},da;for(da in a)a.hasOwnProperty(da)&&
(va[da]=a[da]);var wa=!1,fa=!1,oa=!1,Aa=!1;if(a.ENVIRONMENT)if("WEB"===a.ENVIRONMENT)wa=!0;else if("WORKER"===a.ENVIRONMENT)fa=!0;else if("NODE"===a.ENVIRONMENT)oa=!0;else if("SHELL"===a.ENVIRONMENT)Aa=!0;else throw Error("The provided Module['ENVIRONMENT'] value is not valid. It must be one of: WEB|WORKER|NODE|SHELL.");else wa="object"===typeof window,fa="function"===typeof importScripts,oa="object"===typeof process&&"function"===typeof require&&!wa&&!fa,Aa=!wa&&!oa&&!fa;if(oa){a.print||(a.print=
console.log);a.printErr||(a.printErr=console.warn);var Ma,Na;a.read=function(a,b){Ma||(Ma=require("fs"));Na||(Na=require("path"));a=Na.normalize(a);a=Ma.readFileSync(a);return b?a:a.toString()};a.readBinary=function(d){d=a.read(d,!0);d.buffer||(d=new Uint8Array(d));f(d.buffer);return d};a.load=function(a){h(read(a))};a.thisProgram||(a.thisProgram=1<process.argv.length?process.argv[1].replace(/\\/g,"/"):"unknown-program");a.arguments=process.argv.slice(2);"undefined"!==typeof module&&(module.exports=
a);process.on("uncaughtException",function(a){if(!(a instanceof ma))throw a;});a.inspect=function(){return"[Emscripten Module object]"}}else if(Aa)a.print||(a.print=print),"undefined"!=typeof printErr&&(a.printErr=printErr),a.read="undefined"!=typeof read?read:function(){throw"no read() available";},a.readBinary=function(a){if("function"===typeof readbuffer)return new Uint8Array(readbuffer(a));a=read(a,"binary");f("object"===typeof a);return a},"undefined"!=typeof scriptArgs?a.arguments=scriptArgs:
"undefined"!=typeof arguments&&(a.arguments=arguments),"function"===typeof quit&&(a.quit=function(a,b){quit(a)});else if(wa||fa)a.read=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},fa&&(a.readBinary=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),a.readAsync=function(a,b,c){var d=new XMLHttpRequest;d.open("GET",a,!0);d.responseType="arraybuffer";d.onload=function(){200==
d.status||0==d.status&&d.response?b(d.response):c()};d.onerror=c;d.send(null)},"undefined"!=typeof arguments&&(a.arguments=arguments),"undefined"!==typeof console?(a.print||(a.print=function(a){console.log(a)}),a.printErr||(a.printErr=function(a){console.warn(a)})):a.print||(a.print=function(a){}),fa&&(a.load=importScripts),"undefined"===typeof a.setWindowTitle&&(a.setWindowTitle=function(a){document.title=a});else throw"Unknown runtime environment. Where are we?";!a.load&&a.read&&(a.load=function(d){h(a.read(d))});
a.print||(a.print=function(){});a.printErr||(a.printErr=a.print);a.arguments||(a.arguments=[]);a.thisProgram||(a.thisProgram="./this.program");a.quit||(a.quit=function(a,b){throw b;});a.print=a.print;a.printErr=a.printErr;a.preRun=[];a.postRun=[];for(da in va)va.hasOwnProperty(da)&&(a[da]=va[da]);va=void 0;var n={setTempRet0:function(a){return tempRet0=a},getTempRet0:function(){return tempRet0},stackSave:function(){return T},stackRestore:function(a){T=a},getNativeTypeSize:function(a){switch(a){case "i1":case "i8":return 1;
case "i16":return 2;case "i32":return 4;case "i64":return 8;case "float":return 4;case "double":return 8;default:return"*"===a[a.length-1]?n.QUANTUM_SIZE:"i"===a[0]?(a=parseInt(a.substr(1)),f(0===a%8),a/8):0}},getNativeFieldSize:function(a){return Math.max(n.getNativeTypeSize(a),n.QUANTUM_SIZE)},STACK_ALIGN:16,prepVararg:function(a,b){"double"===b||"i64"===b?a&7&&(f(4===(a&7)),a+=4):f(0===(a&3));return a},getAlignSize:function(a,b,c){return c||"i64"!=a&&"double"!=a?a?Math.min(b||(a?n.getNativeFieldSize(a):
0),n.QUANTUM_SIZE):Math.min(b,8):8},dynCall:function(d,b,c){return c&&c.length?a["dynCall_"+d].apply(null,[b].concat(c)):a["dynCall_"+d].call(null,b)},functionPointers:[],addFunction:function(a){for(var b=0;b<n.functionPointers.length;b++)if(!n.functionPointers[b])return n.functionPointers[b]=a,2*(1+b);throw"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.";},removeFunction:function(a){n.functionPointers[(a-2)/2]=null},warnOnce:function(d){n.warnOnce.shown||
(n.warnOnce.shown={});n.warnOnce.shown[d]||(n.warnOnce.shown[d]=1,a.printErr(d))},funcWrappers:{},getFuncWrapper:function(a,b){f(b);n.funcWrappers[b]||(n.funcWrappers[b]={});var d=n.funcWrappers[b];d[a]||(d[a]=1===b.length?function(){return n.dynCall(b,a)}:2===b.length?function(d){return n.dynCall(b,a,[d])}:function(){return n.dynCall(b,a,Array.prototype.slice.call(arguments))});return d[a]},getCompilerSetting:function(a){throw"You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work";
},stackAlloc:function(a){var b=T;T=T+a|0;T=T+15&-16;return b},staticAlloc:function(a){var b=W;W=W+a|0;W=W+15&-16;return b},dynamicAlloc:function(a){var b=u[X>>2];a=(b+a+15|0)&-16;u[X>>2]=a;return a>=x&&!Va()?(u[X>>2]=b,0):b},alignMemory:function(a,b){return Math.ceil(a/(b?b:16))*(b?b:16)},makeBigInt:function(a,b,c){return c?+(a>>>0)+4294967296*+(b>>>0):+(a>>>0)+4294967296*+(b|0)},GLOBAL_BASE:1024,QUANTUM_SIZE:4,__dummy__:0},oa=0;(function(){function a(a){a=a.toString().match(e).slice(1);return{arguments:a[0],
body:a[1],returnValue:a[2]}}function b(){if(!f){f={};for(var b in c)c.hasOwnProperty(b)&&(f[b]=a(c[b]))}}var c={stackSave:function(){n.stackSave()},stackRestore:function(){n.stackRestore()},arrayToC:function(a){var b=n.stackAlloc(a.length);N.set(a,b);return b},stringToC:function(a){var b=0;if(null!==a&&void 0!==a&&0!==a){var d=(a.length<<2)+1;b=n.stackAlloc(d);Ea(a,G,b,d)}return b}},e=/^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/,f=null;cwrap=function(d,
},stackAlloc:function(a){var b=T;T=T+a|0;T=T+15&-16;return b},staticAlloc:function(a){var b=X;X=X+a|0;X=X+15&-16;return b},dynamicAlloc:function(a){var b=u[Y>>2];a=(b+a+15|0)&-16;u[Y>>2]=a;return a>=x&&!Ua()?(u[Y>>2]=b,0):b},alignMemory:function(a,b){return Math.ceil(a/(b?b:16))*(b?b:16)},makeBigInt:function(a,b,c){return c?+(a>>>0)+4294967296*+(b>>>0):+(a>>>0)+4294967296*+(b|0)},GLOBAL_BASE:1024,QUANTUM_SIZE:4,__dummy__:0},na=0;(function(){function a(a){a=a.toString().match(e).slice(1);return{arguments:a[0],
body:a[1],returnValue:a[2]}}function b(){if(!f){f={};for(var b in c)c.hasOwnProperty(b)&&(f[b]=a(c[b]))}}var c={stackSave:function(){n.stackSave()},stackRestore:function(){n.stackRestore()},arrayToC:function(a){var b=n.stackAlloc(a.length);N.set(a,b);return b},stringToC:function(a){var b=0;if(null!==a&&void 0!==a&&0!==a){var d=(a.length<<2)+1;b=n.stackAlloc(d);Da(a,G,b,d)}return b}},e=/^function\s*[a-zA-Z$_0-9]*\s*\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/,f=null;cwrap=function(d,
c,e){e=e||[];var g=z(d);d=e.every(function(a){return"number"===a});var h="string"!==c;if(h&&d)return g;var k=e.map(function(a,b){return"$"+b});c="(function("+k.join(",")+") {";var l=e.length;if(!d){b();c+="var stack = "+f.stackSave.body+";";for(var m=0;m<l;m++){var A=k[m],n=e[m];"number"!==n&&(n=f[n+"ToC"],c+="var "+n.arguments+" = "+A+";",c+=n.body+";",c+=A+"=("+n.returnValue+");")}}e=a(function(){return g}).returnValue;c+="var ret = "+e+"("+k.join(",")+");";h||(e=a(function(){return t}).returnValue,
c+="ret = "+e+"(ret);");d||(b(),c+=f.stackRestore.body.replace("()","(stack)")+";");return eval(c+"return ret})")}})();var ab="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0;"undefined"!==typeof TextDecoder&&new TextDecoder("utf-16le");var Ja=65536,Ya=16777216,ub=16777216,N,G,sa,Wa,u,Xa,ya,za,W,Pa,T,Ca,Qa,X;var Ra=W=Pa=T=Ca=Qa=X=0;a.reallocBuffer||(a.reallocBuffer=function(a){try{if(ArrayBuffer.transfer)var b=ArrayBuffer.transfer(H,a);else{var d=N;b=new ArrayBuffer(a);(new Int8Array(b)).set(d)}}catch(g){return!1}return Jb(b)?
b:!1});try{var Sa=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,"byteLength").get);Sa(new ArrayBuffer(4))}catch(d){Sa=function(a){return a.byteLength}}var Ta=a.TOTAL_STACK||5242880,x=a.TOTAL_MEMORY||16777216;x<Ta&&a.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was "+x+"! (TOTAL_STACK="+Ta+")");if(a.buffer)var H=a.buffer;else"object"===typeof WebAssembly&&"function"===typeof WebAssembly.Memory?(a.wasmMemory=new WebAssembly.Memory({initial:x/Ja}),H=
a.wasmMemory.buffer):H=new ArrayBuffer(x);ba();u[0]=1668509029;sa[1]=25459;if(115!==G[2]||99!==G[3])throw"Runtime error: expected the system to be little-endian!";a.HEAP=void 0;a.buffer=H;a.HEAP8=N;a.HEAP16=sa;a.HEAP32=u;a.HEAPU8=G;a.HEAPU16=Wa;a.HEAPU32=Xa;a.HEAPF32=ya;a.HEAPF64=za;var fb=[],Ma=[],bb=[],hb=[],db=[],Aa=!1;Math.imul&&-5===Math.imul(4294967295,5)||(Math.imul=function(a,b){var d=a&65535,e=b&65535;return d*e+((a>>>16)*e+d*(b>>>16)<<16)|0});Math.imul=Math.imul;if(!Math.fround){var lb=
new Float32Array(1);Math.fround=function(a){lb[0]=a;return lb[0]}}Math.fround=Math.fround;Math.clz32||(Math.clz32=function(a){a>>>=0;for(var b=0;32>b;b++)if(a&1<<31-b)return b;return 32});Math.clz32=Math.clz32;Math.trunc||(Math.trunc=function(a){return 0>a?Math.ceil(a):Math.floor(a)});Math.trunc=Math.trunc;var qb=Math.abs,tb=Math.ceil,sb=Math.floor,rb=Math.min,fa=0,Ka=null,ta=null;a.preloadedImages={};a.preloadedAudios={};var U=null;(function(d){function b(a,b){var d=t;if(0>a.indexOf("."))d=(d||{})[a];
c+="ret = "+e+"(ret);");d||(b(),c+=f.stackRestore.body.replace("()","(stack)")+";");return eval(c+"return ret})")}})();var $a="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0;"undefined"!==typeof TextDecoder&&new TextDecoder("utf-16le");var Ia=65536,Xa=16777216,tb=16777216,N,G,ra,Va,u,Wa,xa,ya,X,Oa,T,Ba,Pa,Y;var Qa=X=Oa=T=Ba=Pa=Y=0;a.reallocBuffer||(a.reallocBuffer=function(a){try{if(ArrayBuffer.transfer)var b=ArrayBuffer.transfer(H,a);else{var d=N;b=new ArrayBuffer(a);(new Int8Array(b)).set(d)}}catch(g){return!1}return Ib(b)?
b:!1});try{var Ra=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,"byteLength").get);Ra(new ArrayBuffer(4))}catch(d){Ra=function(a){return a.byteLength}}var Sa=a.TOTAL_STACK||5242880,x=a.TOTAL_MEMORY||16777216;x<Sa&&a.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was "+x+"! (TOTAL_STACK="+Sa+")");if(a.buffer)var H=a.buffer;else"object"===typeof WebAssembly&&"function"===typeof WebAssembly.Memory?(a.wasmMemory=new WebAssembly.Memory({initial:x/Ia}),H=
a.wasmMemory.buffer):H=new ArrayBuffer(x);ba();u[0]=1668509029;ra[1]=25459;if(115!==G[2]||99!==G[3])throw"Runtime error: expected the system to be little-endian!";a.HEAP=void 0;a.buffer=H;a.HEAP8=N;a.HEAP16=ra;a.HEAP32=u;a.HEAPU8=G;a.HEAPU16=Va;a.HEAPU32=Wa;a.HEAPF32=xa;a.HEAPF64=ya;var eb=[],La=[],ab=[],gb=[],cb=[],za=!1;Math.imul&&-5===Math.imul(4294967295,5)||(Math.imul=function(a,b){var d=a&65535,e=b&65535;return d*e+((a>>>16)*e+d*(b>>>16)<<16)|0});Math.imul=Math.imul;if(!Math.fround){var kb=
new Float32Array(1);Math.fround=function(a){kb[0]=a;return kb[0]}}Math.fround=Math.fround;Math.clz32||(Math.clz32=function(a){a>>>=0;for(var b=0;32>b;b++)if(a&1<<31-b)return b;return 32});Math.clz32=Math.clz32;Math.trunc||(Math.trunc=function(a){return 0>a?Math.ceil(a):Math.floor(a)});Math.trunc=Math.trunc;var pb=Math.abs,sb=Math.ceil,rb=Math.floor,qb=Math.min,ea=0,Ja=null,sa=null;a.preloadedImages={};a.preloadedAudios={};var U=null;(function(d){function b(a,b){var d=t;if(0>a.indexOf("."))d=(d||{})[a];
else{var c=a.split(".");d=(d||{})[c[0]];d=(d||{})[c[1]]}b&&(d=(d||{})[b]);void 0===d&&M("bad lookupImport to ("+a+")."+b);return d}function c(b){var c=d.buffer;b.byteLength<c.byteLength&&d.printErr("the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here");c=new Int8Array(c);var e=new Int8Array(b);U||c.set(e.subarray(d.STATIC_BASE,d.STATIC_BASE+d.STATIC_BUMP),d.STATIC_BASE);e.set(c);a.buffer=H=b;ba()}function e(){try{if(d.wasmBinary){var a=d.wasmBinary;
a=new Uint8Array(a)}else if(d.readBinary)a=d.readBinary(p);else throw"on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)";return a}catch(Kb){M(Kb)}}function h(){return d.wasmBinary||"function"!==typeof fetch?new Promise(function(a,b){a(e())}):fetch(p,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+p+"'";return a.arrayBuffer()})}function k(a,b,c){if("function"!==
typeof d.asm||d.asm===x)d.asmPreload?d.asm=d.asmPreload:eval(d.read(v));return"function"!==typeof d.asm?(d.printErr("asm evalling did not set the module properly"),!1):d.asm(a,b,c)}function l(a,b,e){function g(a){u=a.exports;u.memory&&c(u.memory);d.asm=u;d.usingWasm=!0;$a("wasm-instantiate")}if("object"!==typeof WebAssembly)return d.printErr("no native wasm support detected"),!1;if(!(d.wasmMemory instanceof WebAssembly.Memory))return d.printErr("no native wasm Memory in use"),!1;b.memory=d.wasmMemory;
t.global={NaN:NaN,Infinity:Infinity};t["global.Math"]=a.Math;t.env=b;Za("wasm-instantiate");if(d.instantiateWasm)try{return d.instantiateWasm(t,g)}catch(Lb){return d.printErr("Module.instantiateWasm callback failed with error: "+Lb),!1}h().then(function(a){return WebAssembly.instantiate(a,t)}).then(function(a){g(a.instance)}).catch(function(a){d.printErr("failed to asynchronously prepare wasm: "+a);M(a)});return{}}var m=d.wasmJSMethod||"native-wasm";d.wasmJSMethod=m;var n=d.wasmTextFile||"draco_decoder.wast",
a=new Uint8Array(a)}else if(d.readBinary)a=d.readBinary(p);else throw"on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)";return a}catch(Jb){M(Jb)}}function h(){return d.wasmBinary||"function"!==typeof fetch?new Promise(function(a,b){a(e())}):fetch(p,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+p+"'";return a.arrayBuffer()})}function k(a,b,c){if("function"!==
typeof d.asm||d.asm===x)d.asmPreload?d.asm=d.asmPreload:eval(d.read(v));return"function"!==typeof d.asm?(d.printErr("asm evalling did not set the module properly"),!1):d.asm(a,b,c)}function l(a,b,e){function g(a){u=a.exports;u.memory&&c(u.memory);d.asm=u;d.usingWasm=!0;Za("wasm-instantiate")}if("object"!==typeof WebAssembly)return d.printErr("no native wasm support detected"),!1;if(!(d.wasmMemory instanceof WebAssembly.Memory))return d.printErr("no native wasm Memory in use"),!1;b.memory=d.wasmMemory;
t.global={NaN:NaN,Infinity:Infinity};t["global.Math"]=a.Math;t.env=b;Ya("wasm-instantiate");if(d.instantiateWasm)try{return d.instantiateWasm(t,g)}catch(Kb){return d.printErr("Module.instantiateWasm callback failed with error: "+Kb),!1}h().then(function(a){return WebAssembly.instantiate(a,t)}).then(function(a){g(a.instance)}).catch(function(a){d.printErr("failed to asynchronously prepare wasm: "+a);M(a)});return{}}var m=d.wasmJSMethod||"native-wasm";d.wasmJSMethod=m;var n=d.wasmTextFile||"draco_decoder.wast",
p=d.wasmBinaryFile||"draco_decoder.wasm",v=d.asmjsCodeFile||"draco_decoder.temp.asm.js";"function"===typeof d.locateFile&&(n=d.locateFile(n),p=d.locateFile(p),v=d.locateFile(v));var t={global:null,env:null,asm2wasm:{"f64-rem":function(a,b){return a%b},"f64-to-int":function(a){return a|0},"i32s-div":function(a,b){return(a|0)/(b|0)|0},"i32u-div":function(a,b){return(a>>>0)/(b>>>0)>>>0},"i32s-rem":function(a,b){return(a|0)%(b|0)|0},"i32u-rem":function(a,b){return(a>>>0)%(b>>>0)>>>0},"debugger":function(){debugger}},
parent:d},u=null;d.asmPreload=d.asm;var q=d.reallocBuffer,r=function(a){a=Fa(a,d.usingWasm?Ja:Ya);var b=d.buffer,c=b.byteLength;if(d.usingWasm)try{return-1!==d.wasmMemory.grow((a-c)/65536)?d.buffer=d.wasmMemory.buffer:null}catch(yd){return null}else return u.__growWasmMemory((a-c)/65536),d.buffer!==b?d.buffer:null};d.reallocBuffer=function(a){return"asmjs"===z?q(a):r(a)};var z="";d.asm=function(a,g,h){if(!g.table){var A=d.wasmTableSize;void 0===A&&(A=1024);var p=d.wasmMaxTableSize;g.table="object"===
parent:d},u=null;d.asmPreload=d.asm;var q=d.reallocBuffer,r=function(a){a=Ea(a,d.usingWasm?Ia:Xa);var b=d.buffer,c=b.byteLength;if(d.usingWasm)try{return-1!==d.wasmMemory.grow((a-c)/65536)?d.buffer=d.wasmMemory.buffer:null}catch(yd){return null}else return u.__growWasmMemory((a-c)/65536),d.buffer!==b?d.buffer:null};d.reallocBuffer=function(a){return"asmjs"===z?q(a):r(a)};var z="";d.asm=function(a,g,h){if(!g.table){var A=d.wasmTableSize;void 0===A&&(A=1024);var p=d.wasmMaxTableSize;g.table="object"===
typeof WebAssembly&&"function"===typeof WebAssembly.Table?void 0!==p?new WebAssembly.Table({initial:A,maximum:p,element:"anyfunc"}):new WebAssembly.Table({initial:A,element:"anyfunc"}):Array(A);d.wasmTable=g.table}g.memoryBase||(g.memoryBase=d.STATIC_BASE);g.tableBase||(g.tableBase=0);var q;A=m.split(",");for(p=0;p<A.length;p++){var w=A[p];z=w;if("native-wasm"===w){if(q=l(a,g,h))break}else if("asmjs"===w){if(q=k(a,g,h))break}else if("interpret-asm2wasm"===w||"interpret-s-expr"===w||"interpret-binary"===
w){q=a;var r=g;var x=h,y=w;if("function"!==typeof WasmJS)d.printErr("WasmJS not detected - polyfill not bundled?"),w=!1;else{w=WasmJS({});w.outside=d;w.info=t;w.lookupImport=b;f(x===d.buffer);t.global=q;t.env=r;f(x===d.buffer);r.memory=x;f(r.memory instanceof ArrayBuffer);w.providedTotalMemory=d.buffer.byteLength;q="interpret-binary"===y?e():d.read("interpret-asm2wasm"==y?v:n);if("interpret-asm2wasm"==y)r=w._malloc(q.length+1),w.writeAsciiToMemory(q,r),w._load_asm2wasm(r);else if("interpret-s-expr"===
y)r=w._malloc(q.length+1),w.writeAsciiToMemory(q,r),w._load_s_expr2wasm(r);else if("interpret-binary"===y)r=w._malloc(q.length),w.HEAPU8.set(q,r),w._load_binary2wasm(r,q.length);else throw"what? "+y;w._free(r);w._instantiate(r);d.newBuffer&&(c(d.newBuffer),d.newBuffer=null);w=u=w.asmExports}if(q=w)break}else M("bad method: "+w)}if(!q)throw"no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods";
return q};var x=d.asm})(a);Ra=n.GLOBAL_BASE;W=Ra+28960;Ma.push();U=0<=a.wasmJSMethod.indexOf("asmjs")||0<=a.wasmJSMethod.indexOf("interpret-asm2wasm")?"draco_decoder.js.mem":null;a.STATIC_BASE=Ra;a.STATIC_BUMP=28960;var Mb=W;W+=16;var C={last:0,caught:[],infos:{},deAdjust:function(a){if(!a||C.infos[a])return a;for(var b in C.infos)if(C.infos[b].adjusted===a)return b;return a},addRef:function(a){a&&C.infos[a].refcount++},decRef:function(d){if(d){var b=C.infos[d];f(0<b.refcount);b.refcount--;0!==b.refcount||
b.rethrown||(b.destructor&&a.dynCall_vi(b.destructor,d),delete C.infos[d],___cxa_free_exception(d))}},clearRef:function(a){a&&(C.infos[a].refcount=0)}};a._memset=Nb;a._memcpy=Ob;var r={varargs:0,get:function(a){r.varargs+=4;return u[r.varargs-4>>2]},getStr:function(){return t(r.get())},get64:function(){var a=r.get(),b=r.get();0<=a?f(0===b):f(-1===b);return a},getZero:function(){f(0===r.get())}},Da={};a._sbrk=Pb;a._memmove=Qb;var Ua=1;a._llvm_bswap_i32=Rb;hb.push(function(){var d=a._fflush;d&&d(0);
if(d=ca.printChar){var b=ca.buffers;b[1].length&&d(1,10);b[2].length&&d(2,10)}});X=R(1,"i32",2);Pa=T=n.alignMemory(W);Ca=Pa+Ta;Qa=n.alignMemory(Ca);u[X>>2]=Qa;a.wasmTableSize=780;a.wasmMaxTableSize=780;a.asmGlobalArg={Math:Math,Int8Array:Int8Array,Int16Array:Int16Array,Int32Array:Int32Array,Uint8Array:Uint8Array,Uint16Array:Uint16Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array,NaN:NaN,Infinity:Infinity,byteLength:Sa};a.asmLibraryArg={abort:M,assert:f,enlargeMemory:Va,
return q};var x=d.asm})(a);Qa=n.GLOBAL_BASE;X=Qa+28928;La.push();U=0<=a.wasmJSMethod.indexOf("asmjs")||0<=a.wasmJSMethod.indexOf("interpret-asm2wasm")?"draco_decoder.js.mem":null;a.STATIC_BASE=Qa;a.STATIC_BUMP=28928;var Lb=X;X+=16;var C={last:0,caught:[],infos:{},deAdjust:function(a){if(!a||C.infos[a])return a;for(var b in C.infos)if(C.infos[b].adjusted===a)return b;return a},addRef:function(a){a&&C.infos[a].refcount++},decRef:function(d){if(d){var b=C.infos[d];f(0<b.refcount);b.refcount--;0!==b.refcount||
b.rethrown||(b.destructor&&a.dynCall_vi(b.destructor,d),delete C.infos[d],___cxa_free_exception(d))}},clearRef:function(a){a&&(C.infos[a].refcount=0)}};a._memset=Mb;a._memcpy=Nb;var r={varargs:0,get:function(a){r.varargs+=4;return u[r.varargs-4>>2]},getStr:function(){return t(r.get())},get64:function(){var a=r.get(),b=r.get();0<=a?f(0===b):f(-1===b);return a},getZero:function(){f(0===r.get())}},Ca={};a._sbrk=Ob;a._memmove=Pb;var Ta=1;a._llvm_bswap_i32=Qb;gb.push(function(){var d=a._fflush;d&&d(0);
if(d=ca.printChar){var b=ca.buffers;b[1].length&&d(1,10);b[2].length&&d(2,10)}});Y=R(1,"i32",2);Oa=T=n.alignMemory(X);Ba=Oa+Sa;Pa=n.alignMemory(Ba);u[Y>>2]=Pa;a.wasmTableSize=780;a.wasmMaxTableSize=780;a.asmGlobalArg={Math:Math,Int8Array:Int8Array,Int16Array:Int16Array,Int32Array:Int32Array,Uint8Array:Uint8Array,Uint16Array:Uint16Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array,NaN:NaN,Infinity:Infinity,byteLength:Ra};a.asmLibraryArg={abort:M,assert:f,enlargeMemory:Ua,
getTotalMemory:function(){return x},abortOnCannotGrowMemory:function(){M("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+x+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")},invoke_iiii:function(d,b,c,e){try{return a.dynCall_iiii(d,b,c,e)}catch(A){if("number"!==typeof A&&"longjmp"!==A)throw A;
a.setThrew(1,0)}},invoke_viiiii:function(d,b,c,e,f,h){try{a.dynCall_viiiii(d,b,c,e,f,h)}catch(S){if("number"!==typeof S&&"longjmp"!==S)throw S;a.setThrew(1,0)}},invoke_vi:function(d,b){try{a.dynCall_vi(d,b)}catch(c){if("number"!==typeof c&&"longjmp"!==c)throw c;a.setThrew(1,0)}},invoke_vii:function(d,b,c){try{a.dynCall_vii(d,b,c)}catch(g){if("number"!==typeof g&&"longjmp"!==g)throw g;a.setThrew(1,0)}},invoke_iiiiiii:function(d,b,c,e,f,h,k){try{return a.dynCall_iiiiiii(d,b,c,e,f,h,k)}catch(y){if("number"!==
typeof y&&"longjmp"!==y)throw y;a.setThrew(1,0)}},invoke_ii:function(d,b){try{return a.dynCall_ii(d,b)}catch(c){if("number"!==typeof c&&"longjmp"!==c)throw c;a.setThrew(1,0)}},invoke_viii:function(d,b,c,e){try{a.dynCall_viii(d,b,c,e)}catch(A){if("number"!==typeof A&&"longjmp"!==A)throw A;a.setThrew(1,0)}},invoke_v:function(d){try{a.dynCall_v(d)}catch(b){if("number"!==typeof b&&"longjmp"!==b)throw b;a.setThrew(1,0)}},invoke_viiiiii:function(d,b,c,e,f,h,k){try{a.dynCall_viiiiii(d,b,c,e,f,h,k)}catch(y){if("number"!==
typeof y&&"longjmp"!==y)throw y;a.setThrew(1,0)}},invoke_iii:function(d,b,c){try{return a.dynCall_iii(d,b,c)}catch(g){if("number"!==typeof g&&"longjmp"!==g)throw g;a.setThrew(1,0)}},invoke_viiii:function(d,b,c,e,f){try{a.dynCall_viiii(d,b,c,e,f)}catch(Ga){if("number"!==typeof Ga&&"longjmp"!==Ga)throw Ga;a.setThrew(1,0)}},_pthread_getspecific:function(a){return Da[a]||0},___syscall54:function(a,b){r.varargs=b;return 0},_pthread_setspecific:function(a,b){if(!(a in Da))return 22;Da[a]=b;return 0},___cxa_throw:function(a,
b,c){C.infos[a]={ptr:a,adjusted:a,type:b,destructor:c,refcount:0,caught:!1,rethrown:!1};C.last=a;"uncaught_exception"in ma?ma.uncaught_exception++:ma.uncaught_exception=1;throw a+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";},___gxx_personality_v0:function(){},_abort:function(){a.abort()},___setErrNo:function(d){a.___errno_location&&(u[a.___errno_location()>>2]=d);return d},___syscall6:function(a,
b){r.varargs=b;try{var c=r.getStreamFromFD();FS.close(c);return 0}catch(g){return"undefined"!==typeof FS&&g instanceof FS.ErrnoError||M(g),-g.errno}},___cxa_begin_catch:function(a){var b=C.infos[a];b&&!b.caught&&(b.caught=!0,ma.uncaught_exception--);b&&(b.rethrown=!1);C.caught.push(a);C.addRef(C.deAdjust(a));return a},___syscall146:ca,_pthread_once:va,_emscripten_memcpy_big:function(a,b,c){G.set(G.subarray(b,b+c),a);return a},_pthread_key_create:function(a,b){if(0==a)return 22;u[a>>2]=Ua;Da[Ua]=0;
Ua++;return 0},___syscall140:function(a,b){r.varargs=b;try{var c=r.getStreamFromFD();r.get();var d=r.get(),e=r.get(),f=r.get();FS.llseek(c,d,f);u[e>>2]=c.position;c.getdents&&0===d&&0===f&&(c.getdents=null);return 0}catch(S){return"undefined"!==typeof FS&&S instanceof FS.ErrnoError||M(S),-S.errno}},___resumeException:function(a){C.last||(C.last=a);throw a+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";
},___cxa_find_matching_catch:ua,___assert_fail:function(a,b,c,e){oa=!0;throw"Assertion failed: "+t(a)+", at: "+[b?t(b):"unknown filename",c,e?t(e):"unknown function"]+" at "+ja();},___cxa_pure_virtual:function(){oa=!0;throw"Pure virtual function called!";},___cxa_allocate_exception:function(a){return la(a)},__ZSt18uncaught_exceptionv:ma,DYNAMICTOP_PTR:X,tempDoublePtr:Mb,ABORT:oa,STACKTOP:T,STACK_MAX:Ca};var mb=a.asm(a.asmGlobalArg,a.asmLibraryArg,H);a.asm=mb;var Sb=a._emscripten_bind_Decoder_GetAttributeFloat_3=
function(){return a.asm._emscripten_bind_Decoder_GetAttributeFloat_3.apply(null,arguments)},Tb=a._emscripten_bind_PointAttribute_normalized_0=function(){return a.asm._emscripten_bind_PointAttribute_normalized_0.apply(null,arguments)},Ub=a._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3=function(){return a.asm._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3.apply(null,arguments)},Vb=a._emscripten_bind_DecoderBuffer_Init_2=function(){return a.asm._emscripten_bind_DecoderBuffer_Init_2.apply(null,
arguments)},Wb=a._emscripten_bind_PointAttribute_size_0=function(){return a.asm._emscripten_bind_PointAttribute_size_0.apply(null,arguments)},Xb=a._emscripten_enum_draco_GeometryAttribute_Type_POSITION=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_POSITION.apply(null,arguments)},Pb=a._sbrk=function(){return a.asm._sbrk.apply(null,arguments)},Ob=a._memcpy=function(){return a.asm._memcpy.apply(null,arguments)};a.stackSave=function(){return a.asm.stackSave.apply(null,arguments)};
var Yb=a._emscripten_enum_draco_GeometryAttribute_Type_INVALID=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_INVALID.apply(null,arguments)},Zb=a._emscripten_bind_Decoder_GetAttributeIdByName_2=function(){return a.asm._emscripten_bind_Decoder_GetAttributeIdByName_2.apply(null,arguments)},$b=a._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD=function(){return a.asm._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD.apply(null,arguments)},ac=a._emscripten_bind_Status_ok_0=
function(){return a.asm._emscripten_bind_Status_ok_0.apply(null,arguments)},bc=a._emscripten_bind_Mesh_num_faces_0=function(){return a.asm._emscripten_bind_Mesh_num_faces_0.apply(null,arguments)};a._emscripten_get_global_libc=function(){return a.asm._emscripten_get_global_libc.apply(null,arguments)};var cc=a._emscripten_bind_Decoder_DecodeBufferToPointCloud_2=function(){return a.asm._emscripten_bind_Decoder_DecodeBufferToPointCloud_2.apply(null,arguments)},dc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM=
function(){return a.asm._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM.apply(null,arguments)};a.runPostSets=function(){return a.asm.runPostSets.apply(null,arguments)};var ec=a._emscripten_bind_Decoder_GetEncodedGeometryType_1=function(){return a.asm._emscripten_bind_Decoder_GetEncodedGeometryType_1.apply(null,arguments)};a.___cxa_can_catch=function(){return a.asm.___cxa_can_catch.apply(null,arguments)};var Ia=a._free=function(){return a.asm._free.apply(null,arguments)},fc=a._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE=
function(){return a.asm._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE.apply(null,arguments)},gc=a._emscripten_bind_GeometryAttribute___destroy___0=function(){return a.asm._emscripten_bind_GeometryAttribute___destroy___0.apply(null,arguments)},hc=a._emscripten_bind_PointAttribute_byte_stride_0=function(){return a.asm._emscripten_bind_PointAttribute_byte_stride_0.apply(null,arguments)},Ib=a._emscripten_bind_Metadata_Metadata_0=function(){return a.asm._emscripten_bind_Metadata_Metadata_0.apply(null,
arguments)},ic=a._emscripten_bind_AttributeQuantizationTransform_min_value_1=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform_min_value_1.apply(null,arguments)},Fb=a._emscripten_bind_Decoder_Decoder_0=function(){return a.asm._emscripten_bind_Decoder_Decoder_0.apply(null,arguments)},jc=a._emscripten_bind_MetadataQuerier_GetStringEntry_2=function(){return a.asm._emscripten_bind_MetadataQuerier_GetStringEntry_2.apply(null,arguments)},kc=a._emscripten_bind_MetadataQuerier_GetIntEntry_2=
function(){return a.asm._emscripten_bind_MetadataQuerier_GetIntEntry_2.apply(null,arguments)},lc=a._emscripten_bind_Decoder___destroy___0=function(){return a.asm._emscripten_bind_Decoder___destroy___0.apply(null,arguments)},mc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM=function(){return a.asm._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM.apply(null,arguments)};a.getTempRet0=function(){return a.asm.getTempRet0.apply(null,arguments)};
a.setThrew=function(){return a.asm.setThrew.apply(null,arguments)};var nc=a._emscripten_bind_MetadataQuerier_HasStringEntry_2=function(){return a.asm._emscripten_bind_MetadataQuerier_HasStringEntry_2.apply(null,arguments)},oc=a._emscripten_bind_AttributeTransformData___destroy___0=function(){return a.asm._emscripten_bind_AttributeTransformData___destroy___0.apply(null,arguments)},pc=a._emscripten_bind_PointAttribute_num_components_0=function(){return a.asm._emscripten_bind_PointAttribute_num_components_0.apply(null,
arguments)};a.___cxa_is_pointer_type=function(){return a.asm.___cxa_is_pointer_type.apply(null,arguments)};var zb=a._emscripten_bind_AttributeTransformData_AttributeTransformData_0=function(){return a.asm._emscripten_bind_AttributeTransformData_AttributeTransformData_0.apply(null,arguments)},qc=a._emscripten_bind_AttributeQuantizationTransform___destroy___0=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform___destroy___0.apply(null,arguments)};a.stackAlloc=function(){return a.asm.stackAlloc.apply(null,
arguments)};var rc=a._emscripten_bind_DracoInt32Array___destroy___0=function(){return a.asm._emscripten_bind_DracoInt32Array___destroy___0.apply(null,arguments)},sc=a._emscripten_bind_Mesh_num_points_0=function(){return a.asm._emscripten_bind_Mesh_num_points_0.apply(null,arguments)},tc=a._emscripten_bind_PointCloud_num_attributes_0=function(){return a.asm._emscripten_bind_PointCloud_num_attributes_0.apply(null,arguments)},Gb=a._emscripten_bind_Mesh_Mesh_0=function(){return a.asm._emscripten_bind_Mesh_Mesh_0.apply(null,
arguments)},Bb=a._emscripten_bind_MetadataQuerier_MetadataQuerier_0=function(){return a.asm._emscripten_bind_MetadataQuerier_MetadataQuerier_0.apply(null,arguments)},uc=a._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3=function(){return a.asm._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3.apply(null,arguments)},vc=a._emscripten_bind_MetadataQuerier_HasDoubleEntry_2=function(){return a.asm._emscripten_bind_MetadataQuerier_HasDoubleEntry_2.apply(null,arguments)},wc=a._emscripten_bind_MetadataQuerier_GetDoubleEntry_2=
function(){return a.asm._emscripten_bind_MetadataQuerier_GetDoubleEntry_2.apply(null,arguments)},xc=a._emscripten_bind_Mesh_num_attributes_0=function(){return a.asm._emscripten_bind_Mesh_num_attributes_0.apply(null,arguments)},yc=a._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0=function(){return a.asm._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0.apply(null,arguments)},zc=a._emscripten_bind_AttributeOctahedronTransform___destroy___0=function(){return a.asm._emscripten_bind_AttributeOctahedronTransform___destroy___0.apply(null,
arguments)},Rb=a._llvm_bswap_i32=function(){return a.asm._llvm_bswap_i32.apply(null,arguments)},Ac=a._emscripten_bind_Decoder_GetAttributeMetadata_2=function(){return a.asm._emscripten_bind_Decoder_GetAttributeMetadata_2.apply(null,arguments)},Bc=a._emscripten_bind_PointAttribute_unique_id_0=function(){return a.asm._emscripten_bind_PointAttribute_unique_id_0.apply(null,arguments)};a.establishStackSpace=function(){return a.asm.establishStackSpace.apply(null,arguments)};var Cc=a._emscripten_enum_draco_StatusCode_IO_ERROR=
function(){return a.asm._emscripten_enum_draco_StatusCode_IO_ERROR.apply(null,arguments)},Dc=a._emscripten_bind_MetadataQuerier_HasIntEntry_2=function(){return a.asm._emscripten_bind_MetadataQuerier_HasIntEntry_2.apply(null,arguments)},Ec=a._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2=function(){return a.asm._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2.apply(null,arguments)},Fc=a._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD.apply(null,
arguments)},Eb=a._emscripten_bind_DecoderBuffer_DecoderBuffer_0=function(){return a.asm._emscripten_bind_DecoderBuffer_DecoderBuffer_0.apply(null,arguments)},Gc=a._emscripten_bind_DracoInt32Array_size_0=function(){return a.asm._emscripten_bind_DracoInt32Array_size_0.apply(null,arguments)},Hc=a._emscripten_bind_Decoder_SkipAttributeTransform_1=function(){return a.asm._emscripten_bind_Decoder_SkipAttributeTransform_1.apply(null,arguments)},Ic=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM=
function(){return a.asm._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM.apply(null,arguments)},Jc=a._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3=function(){return a.asm._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3.apply(null,arguments)},Kc=a._emscripten_enum_draco_StatusCode_ERROR=function(){return a.asm._emscripten_enum_draco_StatusCode_ERROR.apply(null,arguments)},Lc=a._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0.apply(null,
arguments)},Mc=a._emscripten_enum_draco_StatusCode_INVALID_PARAMETER=function(){return a.asm._emscripten_enum_draco_StatusCode_INVALID_PARAMETER.apply(null,arguments)},Nc=a._emscripten_enum_draco_GeometryAttribute_Type_COLOR=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_COLOR.apply(null,arguments)},Oc=a._emscripten_bind_VoidPtr___destroy___0=function(){return a.asm._emscripten_bind_VoidPtr___destroy___0.apply(null,arguments)},Nb=a._memset=function(){return a.asm._memset.apply(null,
arguments)},Pc=a._emscripten_bind_PointAttribute_attribute_type_0=function(){return a.asm._emscripten_bind_PointAttribute_attribute_type_0.apply(null,arguments)},Qc=a._emscripten_bind_MetadataQuerier___destroy___0=function(){return a.asm._emscripten_bind_MetadataQuerier___destroy___0.apply(null,arguments)},Rc=a._emscripten_bind_DracoInt32Array_GetValue_1=function(){return a.asm._emscripten_bind_DracoInt32Array_GetValue_1.apply(null,arguments)},Sc=a._emscripten_bind_DecoderBuffer___destroy___0=function(){return a.asm._emscripten_bind_DecoderBuffer___destroy___0.apply(null,
arguments)},Tc=a._emscripten_bind_Decoder_GetAttribute_2=function(){return a.asm._emscripten_bind_Decoder_GetAttribute_2.apply(null,arguments)},Uc=a._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH=function(){return a.asm._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH.apply(null,arguments)};a.setTempRet0=function(){return a.asm.setTempRet0.apply(null,arguments)};var Hb=a._emscripten_bind_DracoInt32Array_DracoInt32Array_0=function(){return a.asm._emscripten_bind_DracoInt32Array_DracoInt32Array_0.apply(null,
arguments)},Vc=a._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION=function(){return a.asm._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION.apply(null,arguments)},Wc=a._emscripten_bind_DracoFloat32Array___destroy___0=function(){return a.asm._emscripten_bind_DracoFloat32Array___destroy___0.apply(null,arguments)},Xc=a._emscripten_bind_PointCloud_num_points_0=function(){return a.asm._emscripten_bind_PointCloud_num_points_0.apply(null,arguments)},Yc=a._emscripten_bind_PointCloud___destroy___0=function(){return a.asm._emscripten_bind_PointCloud___destroy___0.apply(null,
arguments)},Db=a._emscripten_bind_GeometryAttribute_GeometryAttribute_0=function(){return a.asm._emscripten_bind_GeometryAttribute_GeometryAttribute_0.apply(null,arguments)},Zc=a._emscripten_bind_Decoder_GetFaceFromMesh_3=function(){return a.asm._emscripten_bind_Decoder_GetFaceFromMesh_3.apply(null,arguments)},$c=a._emscripten_bind_PointAttribute_data_type_0=function(){return a.asm._emscripten_bind_PointAttribute_data_type_0.apply(null,arguments)},ad=a._emscripten_bind_DracoFloat32Array_size_0=function(){return a.asm._emscripten_bind_DracoFloat32Array_size_0.apply(null,
arguments)},bd=a._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1=function(){return a.asm._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1.apply(null,arguments)},la=a._malloc=function(){return a.asm._malloc.apply(null,arguments)},cd=a._emscripten_bind_PointAttribute_GetAttributeTransformData_0=function(){return a.asm._emscripten_bind_PointAttribute_GetAttributeTransformData_0.apply(null,arguments)},dd=a._emscripten_bind_PointAttribute_byte_offset_0=function(){return a.asm._emscripten_bind_PointAttribute_byte_offset_0.apply(null,
arguments)},Jb=a._emscripten_replace_memory=function(){return a.asm._emscripten_replace_memory.apply(null,arguments)},Qb=a._memmove=function(){return a.asm._memmove.apply(null,arguments)},wb=a._emscripten_bind_PointCloud_PointCloud_0=function(){return a.asm._emscripten_bind_PointCloud_PointCloud_0.apply(null,arguments)},ed=a._emscripten_bind_Status_error_msg_0=function(){return a.asm._emscripten_bind_Status_error_msg_0.apply(null,arguments)},fd=a._emscripten_bind_Mesh___destroy___0=function(){return a.asm._emscripten_bind_Mesh___destroy___0.apply(null,
arguments)},gd=a._emscripten_bind_Metadata___destroy___0=function(){return a.asm._emscripten_bind_Metadata___destroy___0.apply(null,arguments)},hd=a._emscripten_bind_Status___destroy___0=function(){return a.asm._emscripten_bind_Status___destroy___0.apply(null,arguments)},id=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM=function(){return a.asm._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM.apply(null,arguments)},Ab=a._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0=
function(){return a.asm._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0.apply(null,arguments)},jd=a._emscripten_bind_AttributeQuantizationTransform_range_0=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform_range_0.apply(null,arguments)},kd=a._emscripten_bind_Decoder_GetAttributeId_2=function(){return a.asm._emscripten_bind_Decoder_GetAttributeId_2.apply(null,arguments)},ld=a._emscripten_enum_draco_StatusCode_OK=function(){return a.asm._emscripten_enum_draco_StatusCode_OK.apply(null,
arguments)},md=a._emscripten_bind_AttributeTransformData_transform_type_0=function(){return a.asm._emscripten_bind_AttributeTransformData_transform_type_0.apply(null,arguments)},nd=a._emscripten_bind_Status_code_0=function(){return a.asm._emscripten_bind_Status_code_0.apply(null,arguments)},xb=a._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0=function(){return a.asm._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0.apply(null,arguments)},Cb=
a._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0=function(){return a.asm._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0.apply(null,arguments)},od=a._emscripten_enum_draco_GeometryAttribute_Type_GENERIC=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_GENERIC.apply(null,arguments)},pd=a._emscripten_bind_Decoder_DecodeBufferToMesh_2=function(){return a.asm._emscripten_bind_Decoder_DecodeBufferToMesh_2.apply(null,arguments)},qd=a._emscripten_bind_DracoFloat32Array_GetValue_1=
function(){return a.asm._emscripten_bind_DracoFloat32Array_GetValue_1.apply(null,arguments)},yb=a._emscripten_bind_PointAttribute_PointAttribute_0=function(){return a.asm._emscripten_bind_PointAttribute_PointAttribute_0.apply(null,arguments)},rd=a._emscripten_bind_Decoder_GetMetadata_1=function(){return a.asm._emscripten_bind_Decoder_GetMetadata_1.apply(null,arguments)},sd=a._emscripten_enum_draco_GeometryAttribute_Type_NORMAL=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_NORMAL.apply(null,
arguments)};a.stackRestore=function(){return a.asm.stackRestore.apply(null,arguments)};var td=a._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1.apply(null,arguments)},ud=a._emscripten_bind_PointAttribute___destroy___0=function(){return a.asm._emscripten_bind_PointAttribute___destroy___0.apply(null,arguments)},vd=a._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION=function(){return a.asm._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION.apply(null,
arguments)};a.dynCall_iiii=function(){return a.asm.dynCall_iiii.apply(null,arguments)};a.dynCall_viiiii=function(){return a.asm.dynCall_viiiii.apply(null,arguments)};a.dynCall_vi=function(){return a.asm.dynCall_vi.apply(null,arguments)};a.dynCall_vii=function(){return a.asm.dynCall_vii.apply(null,arguments)};a.dynCall_iiiiiii=function(){return a.asm.dynCall_iiiiiii.apply(null,arguments)};a.dynCall_ii=function(){return a.asm.dynCall_ii.apply(null,arguments)};a.dynCall_viii=function(){return a.asm.dynCall_viii.apply(null,
arguments)};a.dynCall_v=function(){return a.asm.dynCall_v.apply(null,arguments)};a.dynCall_viiiiii=function(){return a.asm.dynCall_viiiiii.apply(null,arguments)};a.dynCall_iii=function(){return a.asm.dynCall_iii.apply(null,arguments)};a.dynCall_viiii=function(){return a.asm.dynCall_viiii.apply(null,arguments)};n.stackAlloc=a.stackAlloc;n.stackSave=a.stackSave;n.stackRestore=a.stackRestore;n.establishStackSpace=a.establishStackSpace;n.setTempRet0=a.setTempRet0;n.getTempRet0=a.getTempRet0;a.asm=mb;
if(U)if("function"===typeof a.locateFile?U=a.locateFile(U):a.memoryInitializerPrefixURL&&(U=a.memoryInitializerPrefixURL+U),pa||Ba){var wd=a.readBinary(U);G.set(wd,n.GLOBAL_BASE)}else{var ob=function(){a.readAsync(U,nb,function(){throw"could not load memory initializer "+U;})};Za("memory initializer");var nb=function(d){d.byteLength&&(d=new Uint8Array(d));G.set(d,n.GLOBAL_BASE);a.memoryInitializerRequest&&delete a.memoryInitializerRequest.response;$a("memory initializer")};if(a.memoryInitializerRequest){var pb=
function(){var d=a.memoryInitializerRequest;200!==d.status&&0!==d.status?(console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+d.status+", retrying "+U),ob()):nb(d.response)};a.memoryInitializerRequest.response?setTimeout(pb,0):a.memoryInitializerRequest.addEventListener("load",pb)}else ob()}a.then=function(d){if(a.calledRun)d(a);else{var b=a.onRuntimeInitialized;a.onRuntimeInitialized=function(){b&&b();d(a)}}return a};na.prototype=Error();na.prototype.constructor=
na;var vb,eb=null;ta=function b(){a.calledRun||La();a.calledRun||(ta=b)};a.callMain=a.callMain=function(b){function c(){for(var a=0;3>a;a++)f.push(0)}b=b||[];Aa||(Aa=!0,ka(Ma));var e=b.length+1,f=[R(ra(a.thisProgram),"i8",0)];c();for(var h=0;h<e-1;h+=1)f.push(R(ra(b[h]),"i8",0)),c();f.push(0);f=R(f,"i32",0);try{var k=a._main(e,f,0);gb(k,!0)}catch(y){y instanceof na||("SimulateInfiniteLoop"==y?a.noExitRuntime=!0:((b=y)&&"object"===typeof y&&y.stack&&(b=[y,y.stack]),a.printErr("exception thrown: "+
b),a.quit(1,y)))}finally{}};a.run=a.run=La;a.exit=a.exit=gb;var ib=[];a.abort=a.abort=M;if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();var cb=!0;a.noInitialRun&&(cb=!1);La();v.prototype=Object.create(v.prototype);v.prototype.constructor=v;v.prototype.__class__=v;v.__cache__={};a.WrapperObject=v;a.getCache=E;a.wrapPointer=Y;a.castObject=function(a,c){return Y(a.ptr,c)};a.NULL=Y(0);a.destroy=function(a){if(!a.__destroy__)throw"Error: Cannot destroy object. (Did you create it yourself?)";
a.__destroy__();delete E(a.__class__)[a.ptr]};a.compare=function(a,c){return a.ptr===c.ptr};a.getPointer=function(a){return a.ptr};a.getClass=function(a){return a.__class__};var k={buffer:0,size:0,pos:0,temps:[],needed:0,prepare:function(){if(k.needed){for(var b=0;b<k.temps.length;b++)a._free(k.temps[b]);k.temps.length=0;a._free(k.buffer);k.buffer=0;k.size+=k.needed;k.needed=0}k.buffer||(k.size+=128,k.buffer=a._malloc(k.size),f(k.buffer));k.pos=0},alloc:function(b,c){f(k.buffer);b=b.length*c.BYTES_PER_ELEMENT;
b=b+7&-8;k.pos+b>=k.size?(f(0<b),k.needed+=b,c=a._malloc(b),k.temps.push(c)):(c=k.buffer+k.pos,k.pos+=b);return c},copy:function(a,c,e){switch(c.BYTES_PER_ELEMENT){case 2:e>>=1;break;case 4:e>>=2;break;case 8:e>>=3}for(var b=0;b<a.length;b++)c[e+b]=a[b]}};D.prototype=Object.create(v.prototype);D.prototype.constructor=D;D.prototype.__class__=D;D.__cache__={};a.Status=D;D.prototype.code=D.prototype.code=function(){return nd(this.ptr)};D.prototype.ok=D.prototype.ok=function(){return!!ac(this.ptr)};D.prototype.error_msg=
D.prototype.error_msg=function(){return t(ed(this.ptr))};D.prototype.__destroy__=D.prototype.__destroy__=function(){hd(this.ptr)};I.prototype=Object.create(v.prototype);I.prototype.constructor=I;I.prototype.__class__=I;I.__cache__={};a.PointCloud=I;I.prototype.num_attributes=I.prototype.num_attributes=function(){return tc(this.ptr)};I.prototype.num_points=I.prototype.num_points=function(){return Xc(this.ptr)};I.prototype.__destroy__=I.prototype.__destroy__=function(){Yc(this.ptr)};J.prototype=Object.create(v.prototype);
J.prototype.constructor=J;J.prototype.__class__=J;J.__cache__={};a.AttributeOctahedronTransform=J;J.prototype.InitFromAttribute=J.prototype.InitFromAttribute=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return!!bd(b,a)};J.prototype.quantization_bits=J.prototype.quantization_bits=function(){return yc(this.ptr)};J.prototype.__destroy__=J.prototype.__destroy__=function(){zc(this.ptr)};p.prototype=Object.create(v.prototype);p.prototype.constructor=p;p.prototype.__class__=p;p.__cache__=
{};a.PointAttribute=p;p.prototype.size=p.prototype.size=function(){return Wb(this.ptr)};p.prototype.GetAttributeTransformData=p.prototype.GetAttributeTransformData=function(){return Y(cd(this.ptr),O)};p.prototype.attribute_type=p.prototype.attribute_type=function(){return Pc(this.ptr)};p.prototype.data_type=p.prototype.data_type=function(){return $c(this.ptr)};p.prototype.num_components=p.prototype.num_components=function(){return pc(this.ptr)};p.prototype.normalized=p.prototype.normalized=function(){return!!Tb(this.ptr)};
p.prototype.byte_stride=p.prototype.byte_stride=function(){return hc(this.ptr)};p.prototype.byte_offset=p.prototype.byte_offset=function(){return dd(this.ptr)};p.prototype.unique_id=p.prototype.unique_id=function(){return Bc(this.ptr)};p.prototype.__destroy__=p.prototype.__destroy__=function(){ud(this.ptr)};O.prototype=Object.create(v.prototype);O.prototype.constructor=O;O.prototype.__class__=O;O.__cache__={};a.AttributeTransformData=O;O.prototype.transform_type=O.prototype.transform_type=function(){return md(this.ptr)};
O.prototype.__destroy__=O.prototype.__destroy__=function(){oc(this.ptr)};B.prototype=Object.create(v.prototype);B.prototype.constructor=B;B.prototype.__class__=B;B.__cache__={};a.AttributeQuantizationTransform=B;B.prototype.InitFromAttribute=B.prototype.InitFromAttribute=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return!!td(b,a)};B.prototype.quantization_bits=B.prototype.quantization_bits=function(){return Lc(this.ptr)};B.prototype.min_value=B.prototype.min_value=function(a){var b=
this.ptr;a&&"object"===typeof a&&(a=a.ptr);return ic(b,a)};B.prototype.range=B.prototype.range=function(){return jd(this.ptr)};B.prototype.__destroy__=B.prototype.__destroy__=function(){qc(this.ptr)};q.prototype=Object.create(v.prototype);q.prototype.constructor=q;q.prototype.__class__=q;q.__cache__={};a.MetadataQuerier=q;q.prototype.HasIntEntry=q.prototype.HasIntEntry=function(a,c){var b=this.ptr;k.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return!!Dc(b,a,c)};
q.prototype.GetIntEntry=q.prototype.GetIntEntry=function(a,c){var b=this.ptr;k.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return kc(b,a,c)};q.prototype.HasDoubleEntry=q.prototype.HasDoubleEntry=function(a,c){var b=this.ptr;k.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return!!vc(b,a,c)};q.prototype.GetDoubleEntry=q.prototype.GetDoubleEntry=function(a,c){var b=this.ptr;k.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===
typeof c?c.ptr:Z(c);return wc(b,a,c)};q.prototype.HasStringEntry=q.prototype.HasStringEntry=function(a,c){var b=this.ptr;k.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return!!nc(b,a,c)};q.prototype.GetStringEntry=q.prototype.GetStringEntry=function(a,c){var b=this.ptr;k.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return t(jc(b,a,c))};q.prototype.__destroy__=q.prototype.__destroy__=function(){Qc(this.ptr)};K.prototype=Object.create(v.prototype);
K.prototype.constructor=K;K.prototype.__class__=K;K.__cache__={};a.DracoFloat32Array=K;K.prototype.GetValue=K.prototype.GetValue=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return qd(b,a)};K.prototype.size=K.prototype.size=function(){return ad(this.ptr)};K.prototype.__destroy__=K.prototype.__destroy__=function(){Wc(this.ptr)};V.prototype=Object.create(v.prototype);V.prototype.constructor=V;V.prototype.__class__=V;V.__cache__={};a.GeometryAttribute=V;V.prototype.__destroy__=V.prototype.__destroy__=
function(){gc(this.ptr)};P.prototype=Object.create(v.prototype);P.prototype.constructor=P;P.prototype.__class__=P;P.__cache__={};a.DecoderBuffer=P;P.prototype.Init=P.prototype.Init=function(a,c){var b=this.ptr;k.prepare();if("object"==typeof a&&"object"===typeof a){var e=k.alloc(a,N);k.copy(a,N,e);a=e}c&&"object"===typeof c&&(c=c.ptr);Vb(b,a,c)};P.prototype.__destroy__=P.prototype.__destroy__=function(){Sc(this.ptr)};l.prototype=Object.create(v.prototype);l.prototype.constructor=l;l.prototype.__class__=
l;l.__cache__={};a.Decoder=l;l.prototype.GetEncodedGeometryType=l.prototype.GetEncodedGeometryType=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return ec(b,a)};l.prototype.DecodeBufferToPointCloud=l.prototype.DecodeBufferToPointCloud=function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return Y(cc(b,a,c),D)};l.prototype.DecodeBufferToMesh=l.prototype.DecodeBufferToMesh=function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===
typeof c&&(c=c.ptr);return Y(pd(b,a,c),D)};l.prototype.GetAttributeId=l.prototype.GetAttributeId=function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return kd(b,a,c)};l.prototype.GetAttributeIdByName=l.prototype.GetAttributeIdByName=function(a,c){var b=this.ptr;k.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return Zb(b,a,c)};l.prototype.GetAttributeIdByMetadataEntry=l.prototype.GetAttributeIdByMetadataEntry=function(a,
c,e){var b=this.ptr;k.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);e=e&&"object"===typeof e?e.ptr:Z(e);return uc(b,a,c,e)};l.prototype.GetAttribute=l.prototype.GetAttribute=function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return Y(Tc(b,a,c),p)};l.prototype.GetMetadata=l.prototype.GetMetadata=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return Y(rd(b,a),Q)};l.prototype.GetAttributeMetadata=l.prototype.GetAttributeMetadata=
function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return Y(Ac(b,a,c),Q)};l.prototype.GetFaceFromMesh=l.prototype.GetFaceFromMesh=function(a,c,e){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);e&&"object"===typeof e&&(e=e.ptr);return!!Zc(b,a,c,e)};l.prototype.GetTriangleStripsFromMesh=l.prototype.GetTriangleStripsFromMesh=function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);
return Ec(b,a,c)};l.prototype.GetAttributeFloat=l.prototype.GetAttributeFloat=function(a,c,e){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);e&&"object"===typeof e&&(e=e.ptr);return!!Sb(b,a,c,e)};l.prototype.GetAttributeFloatForAllPoints=l.prototype.GetAttributeFloatForAllPoints=function(a,c,e){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);e&&"object"===typeof e&&(e=e.ptr);return!!Ub(b,a,c,e)};l.prototype.GetAttributeIntForAllPoints=
l.prototype.GetAttributeIntForAllPoints=function(a,c,e){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);e&&"object"===typeof e&&(e=e.ptr);return!!Jc(b,a,c,e)};l.prototype.SkipAttributeTransform=l.prototype.SkipAttributeTransform=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);Hc(b,a)};l.prototype.__destroy__=l.prototype.__destroy__=function(){lc(this.ptr)};F.prototype=Object.create(v.prototype);F.prototype.constructor=F;F.prototype.__class__=F;F.__cache__=
{};a.Mesh=F;F.prototype.num_faces=F.prototype.num_faces=function(){return bc(this.ptr)};F.prototype.num_attributes=F.prototype.num_attributes=function(){return xc(this.ptr)};F.prototype.num_points=F.prototype.num_points=function(){return sc(this.ptr)};F.prototype.__destroy__=F.prototype.__destroy__=function(){fd(this.ptr)};aa.prototype=Object.create(v.prototype);aa.prototype.constructor=aa;aa.prototype.__class__=aa;aa.__cache__={};a.VoidPtr=aa;aa.prototype.__destroy__=aa.prototype.__destroy__=function(){Oc(this.ptr)};
L.prototype=Object.create(v.prototype);L.prototype.constructor=L;L.prototype.__class__=L;L.__cache__={};a.DracoInt32Array=L;L.prototype.GetValue=L.prototype.GetValue=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return Rc(b,a)};L.prototype.size=L.prototype.size=function(){return Gc(this.ptr)};L.prototype.__destroy__=L.prototype.__destroy__=function(){rc(this.ptr)};Q.prototype=Object.create(v.prototype);Q.prototype.constructor=Q;Q.prototype.__class__=Q;Q.__cache__={};a.Metadata=Q;Q.prototype.__destroy__=
Q.prototype.__destroy__=function(){gd(this.ptr)};(function(){function b(){a.OK=ld();a.ERROR=Kc();a.IO_ERROR=Cc();a.INVALID_PARAMETER=Mc();a.UNSUPPORTED_VERSION=vd();a.UNKNOWN_VERSION=Vc();a.INVALID_GEOMETRY_TYPE=fc();a.POINT_CLOUD=$b();a.TRIANGULAR_MESH=Uc();a.ATTRIBUTE_INVALID_TRANSFORM=id();a.ATTRIBUTE_NO_TRANSFORM=dc();a.ATTRIBUTE_QUANTIZATION_TRANSFORM=Ic();a.ATTRIBUTE_OCTAHEDRON_TRANSFORM=mc();a.INVALID=Yb();a.POSITION=Xb();a.NORMAL=sd();a.COLOR=Nc();a.TEX_COORD=Fc();a.GENERIC=od()}a.calledRun?
b():bb.unshift(b)})();if("function"===typeof a.onModuleParsed)a.onModuleParsed();return e};"object"===typeof module&&module.exports&&(module.exports=DracoDecoderModule);
typeof y&&"longjmp"!==y)throw y;a.setThrew(1,0)}},invoke_iii:function(d,b,c){try{return a.dynCall_iii(d,b,c)}catch(g){if("number"!==typeof g&&"longjmp"!==g)throw g;a.setThrew(1,0)}},invoke_viiii:function(d,b,c,e,f){try{a.dynCall_viiii(d,b,c,e,f)}catch(Fa){if("number"!==typeof Fa&&"longjmp"!==Fa)throw Fa;a.setThrew(1,0)}},_pthread_getspecific:function(a){return Ca[a]||0},___syscall54:function(a,b){r.varargs=b;return 0},_pthread_setspecific:function(a,b){if(!(a in Ca))return 22;Ca[a]=b;return 0},___cxa_throw:function(a,
b,c){C.infos[a]={ptr:a,adjusted:a,type:b,destructor:c,refcount:0,caught:!1,rethrown:!1};C.last=a;"uncaught_exception"in la?la.uncaught_exception++:la.uncaught_exception=1;throw a+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";},___gxx_personality_v0:function(){},_abort:function(){a.abort()},___setErrNo:function(d){a.___errno_location&&(u[a.___errno_location()>>2]=d);return d},___syscall6:function(a,
b){r.varargs=b;try{var c=r.getStreamFromFD();FS.close(c);return 0}catch(g){return"undefined"!==typeof FS&&g instanceof FS.ErrnoError||M(g),-g.errno}},___cxa_begin_catch:function(a){var b=C.infos[a];b&&!b.caught&&(b.caught=!0,la.uncaught_exception--);b&&(b.rethrown=!1);C.caught.push(a);C.addRef(C.deAdjust(a));return a},___syscall146:ca,_pthread_once:ua,_emscripten_memcpy_big:function(a,b,c){G.set(G.subarray(b,b+c),a);return a},_pthread_key_create:function(a,b){if(0==a)return 22;u[a>>2]=Ta;Ca[Ta]=0;
Ta++;return 0},___syscall140:function(a,b){r.varargs=b;try{var c=r.getStreamFromFD();r.get();var d=r.get(),e=r.get(),f=r.get();FS.llseek(c,d,f);u[e>>2]=c.position;c.getdents&&0===d&&0===f&&(c.getdents=null);return 0}catch(S){return"undefined"!==typeof FS&&S instanceof FS.ErrnoError||M(S),-S.errno}},___resumeException:function(a){C.last||(C.last=a);throw a+" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.";
},___cxa_find_matching_catch:ta,___assert_fail:function(a,b,c,e){na=!0;throw"Assertion failed: "+t(a)+", at: "+[b?t(b):"unknown filename",c,e?t(e):"unknown function"]+" at "+ia();},___cxa_pure_virtual:function(){na=!0;throw"Pure virtual function called!";},___cxa_allocate_exception:function(a){return ka(a)},__ZSt18uncaught_exceptionv:la,DYNAMICTOP_PTR:Y,tempDoublePtr:Lb,ABORT:na,STACKTOP:T,STACK_MAX:Ba};var lb=a.asm(a.asmGlobalArg,a.asmLibraryArg,H);a.asm=lb;var Rb=a._emscripten_bind_Decoder_GetAttributeFloat_3=
function(){return a.asm._emscripten_bind_Decoder_GetAttributeFloat_3.apply(null,arguments)},Sb=a._emscripten_bind_PointAttribute_normalized_0=function(){return a.asm._emscripten_bind_PointAttribute_normalized_0.apply(null,arguments)},Tb=a._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3=function(){return a.asm._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3.apply(null,arguments)},Ub=a._emscripten_bind_DecoderBuffer_Init_2=function(){return a.asm._emscripten_bind_DecoderBuffer_Init_2.apply(null,
arguments)},Vb=a._emscripten_bind_PointAttribute_size_0=function(){return a.asm._emscripten_bind_PointAttribute_size_0.apply(null,arguments)},Wb=a._emscripten_enum_draco_GeometryAttribute_Type_POSITION=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_POSITION.apply(null,arguments)},Ob=a._sbrk=function(){return a.asm._sbrk.apply(null,arguments)},Nb=a._memcpy=function(){return a.asm._memcpy.apply(null,arguments)};a.stackSave=function(){return a.asm.stackSave.apply(null,arguments)};
var Xb=a._emscripten_enum_draco_GeometryAttribute_Type_INVALID=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_INVALID.apply(null,arguments)},Yb=a._emscripten_bind_Decoder_GetAttributeIdByName_2=function(){return a.asm._emscripten_bind_Decoder_GetAttributeIdByName_2.apply(null,arguments)},Zb=a._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD=function(){return a.asm._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD.apply(null,arguments)},$b=a._emscripten_bind_Status_ok_0=
function(){return a.asm._emscripten_bind_Status_ok_0.apply(null,arguments)},ac=a._emscripten_bind_Mesh_num_faces_0=function(){return a.asm._emscripten_bind_Mesh_num_faces_0.apply(null,arguments)};a._emscripten_get_global_libc=function(){return a.asm._emscripten_get_global_libc.apply(null,arguments)};var bc=a._emscripten_bind_Decoder_DecodeBufferToPointCloud_2=function(){return a.asm._emscripten_bind_Decoder_DecodeBufferToPointCloud_2.apply(null,arguments)},cc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM=
function(){return a.asm._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM.apply(null,arguments)};a.runPostSets=function(){return a.asm.runPostSets.apply(null,arguments)};var dc=a._emscripten_bind_Decoder_GetEncodedGeometryType_1=function(){return a.asm._emscripten_bind_Decoder_GetEncodedGeometryType_1.apply(null,arguments)};a.___cxa_can_catch=function(){return a.asm.___cxa_can_catch.apply(null,arguments)};var Ha=a._free=function(){return a.asm._free.apply(null,arguments)},ec=a._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE=
function(){return a.asm._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE.apply(null,arguments)},fc=a._emscripten_bind_GeometryAttribute___destroy___0=function(){return a.asm._emscripten_bind_GeometryAttribute___destroy___0.apply(null,arguments)},gc=a._emscripten_bind_PointAttribute_byte_stride_0=function(){return a.asm._emscripten_bind_PointAttribute_byte_stride_0.apply(null,arguments)},Hb=a._emscripten_bind_Metadata_Metadata_0=function(){return a.asm._emscripten_bind_Metadata_Metadata_0.apply(null,
arguments)},hc=a._emscripten_bind_AttributeQuantizationTransform_min_value_1=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform_min_value_1.apply(null,arguments)},Eb=a._emscripten_bind_Decoder_Decoder_0=function(){return a.asm._emscripten_bind_Decoder_Decoder_0.apply(null,arguments)},ic=a._emscripten_bind_MetadataQuerier_GetStringEntry_2=function(){return a.asm._emscripten_bind_MetadataQuerier_GetStringEntry_2.apply(null,arguments)},jc=a._emscripten_bind_MetadataQuerier_GetIntEntry_2=
function(){return a.asm._emscripten_bind_MetadataQuerier_GetIntEntry_2.apply(null,arguments)},kc=a._emscripten_bind_Decoder___destroy___0=function(){return a.asm._emscripten_bind_Decoder___destroy___0.apply(null,arguments)},lc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM=function(){return a.asm._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM.apply(null,arguments)};a.getTempRet0=function(){return a.asm.getTempRet0.apply(null,arguments)};
a.setThrew=function(){return a.asm.setThrew.apply(null,arguments)};var mc=a._emscripten_bind_MetadataQuerier_HasStringEntry_2=function(){return a.asm._emscripten_bind_MetadataQuerier_HasStringEntry_2.apply(null,arguments)},nc=a._emscripten_bind_AttributeTransformData___destroy___0=function(){return a.asm._emscripten_bind_AttributeTransformData___destroy___0.apply(null,arguments)},oc=a._emscripten_bind_PointAttribute_num_components_0=function(){return a.asm._emscripten_bind_PointAttribute_num_components_0.apply(null,
arguments)};a.___cxa_is_pointer_type=function(){return a.asm.___cxa_is_pointer_type.apply(null,arguments)};var yb=a._emscripten_bind_AttributeTransformData_AttributeTransformData_0=function(){return a.asm._emscripten_bind_AttributeTransformData_AttributeTransformData_0.apply(null,arguments)},pc=a._emscripten_bind_AttributeQuantizationTransform___destroy___0=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform___destroy___0.apply(null,arguments)};a.stackAlloc=function(){return a.asm.stackAlloc.apply(null,
arguments)};var qc=a._emscripten_bind_DracoInt32Array___destroy___0=function(){return a.asm._emscripten_bind_DracoInt32Array___destroy___0.apply(null,arguments)},rc=a._emscripten_bind_Mesh_num_points_0=function(){return a.asm._emscripten_bind_Mesh_num_points_0.apply(null,arguments)},sc=a._emscripten_bind_PointCloud_num_attributes_0=function(){return a.asm._emscripten_bind_PointCloud_num_attributes_0.apply(null,arguments)},Fb=a._emscripten_bind_Mesh_Mesh_0=function(){return a.asm._emscripten_bind_Mesh_Mesh_0.apply(null,
arguments)},Ab=a._emscripten_bind_MetadataQuerier_MetadataQuerier_0=function(){return a.asm._emscripten_bind_MetadataQuerier_MetadataQuerier_0.apply(null,arguments)},tc=a._emscripten_bind_Decoder_GetAttributeByUniqueId_2=function(){return a.asm._emscripten_bind_Decoder_GetAttributeByUniqueId_2.apply(null,arguments)},uc=a._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3=function(){return a.asm._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3.apply(null,arguments)},vc=a._emscripten_bind_MetadataQuerier_HasDoubleEntry_2=
function(){return a.asm._emscripten_bind_MetadataQuerier_HasDoubleEntry_2.apply(null,arguments)},wc=a._emscripten_bind_MetadataQuerier_GetDoubleEntry_2=function(){return a.asm._emscripten_bind_MetadataQuerier_GetDoubleEntry_2.apply(null,arguments)},xc=a._emscripten_bind_Mesh_num_attributes_0=function(){return a.asm._emscripten_bind_Mesh_num_attributes_0.apply(null,arguments)},yc=a._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0=function(){return a.asm._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0.apply(null,
arguments)},zc=a._emscripten_bind_AttributeOctahedronTransform___destroy___0=function(){return a.asm._emscripten_bind_AttributeOctahedronTransform___destroy___0.apply(null,arguments)},Qb=a._llvm_bswap_i32=function(){return a.asm._llvm_bswap_i32.apply(null,arguments)},Ac=a._emscripten_bind_Decoder_GetAttributeMetadata_2=function(){return a.asm._emscripten_bind_Decoder_GetAttributeMetadata_2.apply(null,arguments)},Bc=a._emscripten_bind_PointAttribute_unique_id_0=function(){return a.asm._emscripten_bind_PointAttribute_unique_id_0.apply(null,
arguments)};a.establishStackSpace=function(){return a.asm.establishStackSpace.apply(null,arguments)};var Cc=a._emscripten_enum_draco_StatusCode_IO_ERROR=function(){return a.asm._emscripten_enum_draco_StatusCode_IO_ERROR.apply(null,arguments)},Dc=a._emscripten_bind_MetadataQuerier_HasIntEntry_2=function(){return a.asm._emscripten_bind_MetadataQuerier_HasIntEntry_2.apply(null,arguments)},Ec=a._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2=function(){return a.asm._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2.apply(null,
arguments)},Fc=a._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD.apply(null,arguments)},Db=a._emscripten_bind_DecoderBuffer_DecoderBuffer_0=function(){return a.asm._emscripten_bind_DecoderBuffer_DecoderBuffer_0.apply(null,arguments)},Gc=a._emscripten_bind_DracoInt32Array_size_0=function(){return a.asm._emscripten_bind_DracoInt32Array_size_0.apply(null,arguments)},Hc=a._emscripten_bind_Decoder_SkipAttributeTransform_1=
function(){return a.asm._emscripten_bind_Decoder_SkipAttributeTransform_1.apply(null,arguments)},Ic=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM=function(){return a.asm._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM.apply(null,arguments)},Jc=a._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3=function(){return a.asm._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3.apply(null,arguments)},Kc=a._emscripten_enum_draco_StatusCode_ERROR=
function(){return a.asm._emscripten_enum_draco_StatusCode_ERROR.apply(null,arguments)},Lc=a._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0.apply(null,arguments)},Mc=a._emscripten_enum_draco_StatusCode_INVALID_PARAMETER=function(){return a.asm._emscripten_enum_draco_StatusCode_INVALID_PARAMETER.apply(null,arguments)},Nc=a._emscripten_enum_draco_GeometryAttribute_Type_COLOR=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_COLOR.apply(null,
arguments)},Oc=a._emscripten_bind_VoidPtr___destroy___0=function(){return a.asm._emscripten_bind_VoidPtr___destroy___0.apply(null,arguments)},Mb=a._memset=function(){return a.asm._memset.apply(null,arguments)},Pc=a._emscripten_bind_PointAttribute_attribute_type_0=function(){return a.asm._emscripten_bind_PointAttribute_attribute_type_0.apply(null,arguments)},Qc=a._emscripten_bind_MetadataQuerier___destroy___0=function(){return a.asm._emscripten_bind_MetadataQuerier___destroy___0.apply(null,arguments)},
Rc=a._emscripten_bind_DracoInt32Array_GetValue_1=function(){return a.asm._emscripten_bind_DracoInt32Array_GetValue_1.apply(null,arguments)},Sc=a._emscripten_bind_DecoderBuffer___destroy___0=function(){return a.asm._emscripten_bind_DecoderBuffer___destroy___0.apply(null,arguments)},Tc=a._emscripten_bind_Decoder_GetAttribute_2=function(){return a.asm._emscripten_bind_Decoder_GetAttribute_2.apply(null,arguments)},Uc=a._emscripten_bind_PointCloud___destroy___0=function(){return a.asm._emscripten_bind_PointCloud___destroy___0.apply(null,
arguments)};a.setTempRet0=function(){return a.asm.setTempRet0.apply(null,arguments)};var Gb=a._emscripten_bind_DracoInt32Array_DracoInt32Array_0=function(){return a.asm._emscripten_bind_DracoInt32Array_DracoInt32Array_0.apply(null,arguments)},Vc=a._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION=function(){return a.asm._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION.apply(null,arguments)},Wc=a._emscripten_bind_DracoFloat32Array___destroy___0=function(){return a.asm._emscripten_bind_DracoFloat32Array___destroy___0.apply(null,
arguments)},Xc=a._emscripten_bind_PointCloud_num_points_0=function(){return a.asm._emscripten_bind_PointCloud_num_points_0.apply(null,arguments)},Yc=a._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH=function(){return a.asm._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH.apply(null,arguments)},Cb=a._emscripten_bind_GeometryAttribute_GeometryAttribute_0=function(){return a.asm._emscripten_bind_GeometryAttribute_GeometryAttribute_0.apply(null,arguments)},Zc=a._emscripten_bind_Decoder_GetFaceFromMesh_3=
function(){return a.asm._emscripten_bind_Decoder_GetFaceFromMesh_3.apply(null,arguments)},$c=a._emscripten_bind_PointAttribute_data_type_0=function(){return a.asm._emscripten_bind_PointAttribute_data_type_0.apply(null,arguments)},ad=a._emscripten_bind_DracoFloat32Array_size_0=function(){return a.asm._emscripten_bind_DracoFloat32Array_size_0.apply(null,arguments)},bd=a._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1=function(){return a.asm._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1.apply(null,
arguments)},ka=a._malloc=function(){return a.asm._malloc.apply(null,arguments)},cd=a._emscripten_bind_PointAttribute_GetAttributeTransformData_0=function(){return a.asm._emscripten_bind_PointAttribute_GetAttributeTransformData_0.apply(null,arguments)},dd=a._emscripten_bind_PointAttribute_byte_offset_0=function(){return a.asm._emscripten_bind_PointAttribute_byte_offset_0.apply(null,arguments)},Ib=a._emscripten_replace_memory=function(){return a.asm._emscripten_replace_memory.apply(null,arguments)},
Pb=a._memmove=function(){return a.asm._memmove.apply(null,arguments)},vb=a._emscripten_bind_PointCloud_PointCloud_0=function(){return a.asm._emscripten_bind_PointCloud_PointCloud_0.apply(null,arguments)},ed=a._emscripten_bind_Status_error_msg_0=function(){return a.asm._emscripten_bind_Status_error_msg_0.apply(null,arguments)},fd=a._emscripten_bind_Mesh___destroy___0=function(){return a.asm._emscripten_bind_Mesh___destroy___0.apply(null,arguments)},gd=a._emscripten_bind_Metadata___destroy___0=function(){return a.asm._emscripten_bind_Metadata___destroy___0.apply(null,
arguments)},hd=a._emscripten_bind_Status___destroy___0=function(){return a.asm._emscripten_bind_Status___destroy___0.apply(null,arguments)},id=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM=function(){return a.asm._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM.apply(null,arguments)},zb=a._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0.apply(null,
arguments)},jd=a._emscripten_bind_AttributeQuantizationTransform_range_0=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform_range_0.apply(null,arguments)},kd=a._emscripten_bind_Decoder_GetAttributeId_2=function(){return a.asm._emscripten_bind_Decoder_GetAttributeId_2.apply(null,arguments)},ld=a._emscripten_enum_draco_StatusCode_OK=function(){return a.asm._emscripten_enum_draco_StatusCode_OK.apply(null,arguments)},md=a._emscripten_bind_AttributeTransformData_transform_type_0=function(){return a.asm._emscripten_bind_AttributeTransformData_transform_type_0.apply(null,
arguments)},nd=a._emscripten_bind_Status_code_0=function(){return a.asm._emscripten_bind_Status_code_0.apply(null,arguments)},wb=a._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0=function(){return a.asm._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0.apply(null,arguments)},Bb=a._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0=function(){return a.asm._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0.apply(null,arguments)},od=a._emscripten_enum_draco_GeometryAttribute_Type_GENERIC=
function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_GENERIC.apply(null,arguments)},pd=a._emscripten_bind_Decoder_DecodeBufferToMesh_2=function(){return a.asm._emscripten_bind_Decoder_DecodeBufferToMesh_2.apply(null,arguments)},qd=a._emscripten_bind_DracoFloat32Array_GetValue_1=function(){return a.asm._emscripten_bind_DracoFloat32Array_GetValue_1.apply(null,arguments)},xb=a._emscripten_bind_PointAttribute_PointAttribute_0=function(){return a.asm._emscripten_bind_PointAttribute_PointAttribute_0.apply(null,
arguments)},rd=a._emscripten_bind_Decoder_GetMetadata_1=function(){return a.asm._emscripten_bind_Decoder_GetMetadata_1.apply(null,arguments)},sd=a._emscripten_enum_draco_GeometryAttribute_Type_NORMAL=function(){return a.asm._emscripten_enum_draco_GeometryAttribute_Type_NORMAL.apply(null,arguments)};a.stackRestore=function(){return a.asm.stackRestore.apply(null,arguments)};var td=a._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1=function(){return a.asm._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1.apply(null,
arguments)},ud=a._emscripten_bind_PointAttribute___destroy___0=function(){return a.asm._emscripten_bind_PointAttribute___destroy___0.apply(null,arguments)},vd=a._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION=function(){return a.asm._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION.apply(null,arguments)};a.dynCall_iiii=function(){return a.asm.dynCall_iiii.apply(null,arguments)};a.dynCall_viiiii=function(){return a.asm.dynCall_viiiii.apply(null,arguments)};a.dynCall_vi=function(){return a.asm.dynCall_vi.apply(null,
arguments)};a.dynCall_vii=function(){return a.asm.dynCall_vii.apply(null,arguments)};a.dynCall_iiiiiii=function(){return a.asm.dynCall_iiiiiii.apply(null,arguments)};a.dynCall_ii=function(){return a.asm.dynCall_ii.apply(null,arguments)};a.dynCall_viii=function(){return a.asm.dynCall_viii.apply(null,arguments)};a.dynCall_v=function(){return a.asm.dynCall_v.apply(null,arguments)};a.dynCall_viiiiii=function(){return a.asm.dynCall_viiiiii.apply(null,arguments)};a.dynCall_iii=function(){return a.asm.dynCall_iii.apply(null,
arguments)};a.dynCall_viiii=function(){return a.asm.dynCall_viiii.apply(null,arguments)};n.stackAlloc=a.stackAlloc;n.stackSave=a.stackSave;n.stackRestore=a.stackRestore;n.establishStackSpace=a.establishStackSpace;n.setTempRet0=a.setTempRet0;n.getTempRet0=a.getTempRet0;a.asm=lb;if(U)if("function"===typeof a.locateFile?U=a.locateFile(U):a.memoryInitializerPrefixURL&&(U=a.memoryInitializerPrefixURL+U),oa||Aa){var wd=a.readBinary(U);G.set(wd,n.GLOBAL_BASE)}else{var nb=function(){a.readAsync(U,mb,function(){throw"could not load memory initializer "+
U;})};Ya("memory initializer");var mb=function(d){d.byteLength&&(d=new Uint8Array(d));G.set(d,n.GLOBAL_BASE);a.memoryInitializerRequest&&delete a.memoryInitializerRequest.response;Za("memory initializer")};if(a.memoryInitializerRequest){var ob=function(){var d=a.memoryInitializerRequest;200!==d.status&&0!==d.status?(console.warn("a problem seems to have happened with Module.memoryInitializerRequest, status: "+d.status+", retrying "+U),nb()):mb(d.response)};a.memoryInitializerRequest.response?setTimeout(ob,
0):a.memoryInitializerRequest.addEventListener("load",ob)}else nb()}a.then=function(d){if(a.calledRun)d(a);else{var b=a.onRuntimeInitialized;a.onRuntimeInitialized=function(){b&&b();d(a)}}return a};ma.prototype=Error();ma.prototype.constructor=ma;var ub,db=null;sa=function b(){a.calledRun||Ka();a.calledRun||(sa=b)};a.callMain=a.callMain=function(b){function c(){for(var a=0;3>a;a++)f.push(0)}b=b||[];za||(za=!0,ja(La));var e=b.length+1,f=[R(qa(a.thisProgram),"i8",0)];c();for(var h=0;h<e-1;h+=1)f.push(R(qa(b[h]),
"i8",0)),c();f.push(0);f=R(f,"i32",0);try{var k=a._main(e,f,0);fb(k,!0)}catch(y){y instanceof ma||("SimulateInfiniteLoop"==y?a.noExitRuntime=!0:((b=y)&&"object"===typeof y&&y.stack&&(b=[y,y.stack]),a.printErr("exception thrown: "+b),a.quit(1,y)))}finally{}};a.run=a.run=Ka;a.exit=a.exit=fb;var hb=[];a.abort=a.abort=M;if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();var bb=!0;a.noInitialRun&&(bb=!1);Ka();v.prototype=Object.create(v.prototype);
v.prototype.constructor=v;v.prototype.__class__=v;v.__cache__={};a.WrapperObject=v;a.getCache=E;a.wrapPointer=V;a.castObject=function(a,c){return V(a.ptr,c)};a.NULL=V(0);a.destroy=function(a){if(!a.__destroy__)throw"Error: Cannot destroy object. (Did you create it yourself?)";a.__destroy__();delete E(a.__class__)[a.ptr]};a.compare=function(a,c){return a.ptr===c.ptr};a.getPointer=function(a){return a.ptr};a.getClass=function(a){return a.__class__};var l={buffer:0,size:0,pos:0,temps:[],needed:0,prepare:function(){if(l.needed){for(var b=
0;b<l.temps.length;b++)a._free(l.temps[b]);l.temps.length=0;a._free(l.buffer);l.buffer=0;l.size+=l.needed;l.needed=0}l.buffer||(l.size+=128,l.buffer=a._malloc(l.size),f(l.buffer));l.pos=0},alloc:function(b,c){f(l.buffer);b=b.length*c.BYTES_PER_ELEMENT;b=b+7&-8;l.pos+b>=l.size?(f(0<b),l.needed+=b,c=a._malloc(b),l.temps.push(c)):(c=l.buffer+l.pos,l.pos+=b);return c},copy:function(a,c,e){switch(c.BYTES_PER_ELEMENT){case 2:e>>=1;break;case 4:e>>=2;break;case 8:e>>=3}for(var b=0;b<a.length;b++)c[e+b]=
a[b]}};D.prototype=Object.create(v.prototype);D.prototype.constructor=D;D.prototype.__class__=D;D.__cache__={};a.Status=D;D.prototype.code=D.prototype.code=function(){return nd(this.ptr)};D.prototype.ok=D.prototype.ok=function(){return!!$b(this.ptr)};D.prototype.error_msg=D.prototype.error_msg=function(){return t(ed(this.ptr))};D.prototype.__destroy__=D.prototype.__destroy__=function(){hd(this.ptr)};I.prototype=Object.create(v.prototype);I.prototype.constructor=I;I.prototype.__class__=I;I.__cache__=
{};a.PointCloud=I;I.prototype.num_attributes=I.prototype.num_attributes=function(){return sc(this.ptr)};I.prototype.num_points=I.prototype.num_points=function(){return Xc(this.ptr)};I.prototype.__destroy__=I.prototype.__destroy__=function(){Uc(this.ptr)};J.prototype=Object.create(v.prototype);J.prototype.constructor=J;J.prototype.__class__=J;J.__cache__={};a.AttributeOctahedronTransform=J;J.prototype.InitFromAttribute=J.prototype.InitFromAttribute=function(a){var b=this.ptr;a&&"object"===typeof a&&
(a=a.ptr);return!!bd(b,a)};J.prototype.quantization_bits=J.prototype.quantization_bits=function(){return yc(this.ptr)};J.prototype.__destroy__=J.prototype.__destroy__=function(){zc(this.ptr)};p.prototype=Object.create(v.prototype);p.prototype.constructor=p;p.prototype.__class__=p;p.__cache__={};a.PointAttribute=p;p.prototype.size=p.prototype.size=function(){return Vb(this.ptr)};p.prototype.GetAttributeTransformData=p.prototype.GetAttributeTransformData=function(){return V(cd(this.ptr),O)};p.prototype.attribute_type=
p.prototype.attribute_type=function(){return Pc(this.ptr)};p.prototype.data_type=p.prototype.data_type=function(){return $c(this.ptr)};p.prototype.num_components=p.prototype.num_components=function(){return oc(this.ptr)};p.prototype.normalized=p.prototype.normalized=function(){return!!Sb(this.ptr)};p.prototype.byte_stride=p.prototype.byte_stride=function(){return gc(this.ptr)};p.prototype.byte_offset=p.prototype.byte_offset=function(){return dd(this.ptr)};p.prototype.unique_id=p.prototype.unique_id=
function(){return Bc(this.ptr)};p.prototype.__destroy__=p.prototype.__destroy__=function(){ud(this.ptr)};O.prototype=Object.create(v.prototype);O.prototype.constructor=O;O.prototype.__class__=O;O.__cache__={};a.AttributeTransformData=O;O.prototype.transform_type=O.prototype.transform_type=function(){return md(this.ptr)};O.prototype.__destroy__=O.prototype.__destroy__=function(){nc(this.ptr)};B.prototype=Object.create(v.prototype);B.prototype.constructor=B;B.prototype.__class__=B;B.__cache__={};a.AttributeQuantizationTransform=
B;B.prototype.InitFromAttribute=B.prototype.InitFromAttribute=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return!!td(b,a)};B.prototype.quantization_bits=B.prototype.quantization_bits=function(){return Lc(this.ptr)};B.prototype.min_value=B.prototype.min_value=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return hc(b,a)};B.prototype.range=B.prototype.range=function(){return jd(this.ptr)};B.prototype.__destroy__=B.prototype.__destroy__=function(){pc(this.ptr)};q.prototype=
Object.create(v.prototype);q.prototype.constructor=q;q.prototype.__class__=q;q.__cache__={};a.MetadataQuerier=q;q.prototype.HasIntEntry=q.prototype.HasIntEntry=function(a,c){var b=this.ptr;l.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return!!Dc(b,a,c)};q.prototype.GetIntEntry=q.prototype.GetIntEntry=function(a,c){var b=this.ptr;l.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return jc(b,a,c)};q.prototype.HasDoubleEntry=q.prototype.HasDoubleEntry=
function(a,c){var b=this.ptr;l.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return!!vc(b,a,c)};q.prototype.GetDoubleEntry=q.prototype.GetDoubleEntry=function(a,c){var b=this.ptr;l.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return wc(b,a,c)};q.prototype.HasStringEntry=q.prototype.HasStringEntry=function(a,c){var b=this.ptr;l.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return!!mc(b,a,c)};q.prototype.GetStringEntry=
q.prototype.GetStringEntry=function(a,c){var b=this.ptr;l.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return t(ic(b,a,c))};q.prototype.__destroy__=q.prototype.__destroy__=function(){Qc(this.ptr)};K.prototype=Object.create(v.prototype);K.prototype.constructor=K;K.prototype.__class__=K;K.__cache__={};a.DracoFloat32Array=K;K.prototype.GetValue=K.prototype.GetValue=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return qd(b,a)};K.prototype.size=K.prototype.size=
function(){return ad(this.ptr)};K.prototype.__destroy__=K.prototype.__destroy__=function(){Wc(this.ptr)};W.prototype=Object.create(v.prototype);W.prototype.constructor=W;W.prototype.__class__=W;W.__cache__={};a.GeometryAttribute=W;W.prototype.__destroy__=W.prototype.__destroy__=function(){fc(this.ptr)};P.prototype=Object.create(v.prototype);P.prototype.constructor=P;P.prototype.__class__=P;P.__cache__={};a.DecoderBuffer=P;P.prototype.Init=P.prototype.Init=function(a,c){var b=this.ptr;l.prepare();
if("object"==typeof a&&"object"===typeof a){var e=l.alloc(a,N);l.copy(a,N,e);a=e}c&&"object"===typeof c&&(c=c.ptr);Ub(b,a,c)};P.prototype.__destroy__=P.prototype.__destroy__=function(){Sc(this.ptr)};m.prototype=Object.create(v.prototype);m.prototype.constructor=m;m.prototype.__class__=m;m.__cache__={};a.Decoder=m;m.prototype.GetEncodedGeometryType=m.prototype.GetEncodedGeometryType=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return dc(b,a)};m.prototype.DecodeBufferToPointCloud=m.prototype.DecodeBufferToPointCloud=
function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return V(bc(b,a,c),D)};m.prototype.DecodeBufferToMesh=m.prototype.DecodeBufferToMesh=function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return V(pd(b,a,c),D)};m.prototype.GetAttributeId=m.prototype.GetAttributeId=function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return kd(b,a,c)};m.prototype.GetAttributeIdByName=
m.prototype.GetAttributeIdByName=function(a,c){var b=this.ptr;l.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);return Yb(b,a,c)};m.prototype.GetAttributeIdByMetadataEntry=m.prototype.GetAttributeIdByMetadataEntry=function(a,c,e){var b=this.ptr;l.prepare();a&&"object"===typeof a&&(a=a.ptr);c=c&&"object"===typeof c?c.ptr:Z(c);e=e&&"object"===typeof e?e.ptr:Z(e);return uc(b,a,c,e)};m.prototype.GetAttribute=m.prototype.GetAttribute=function(a,c){var b=this.ptr;a&&"object"===
typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return V(Tc(b,a,c),p)};m.prototype.GetAttributeByUniqueId=m.prototype.GetAttributeByUniqueId=function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return V(tc(b,a,c),p)};m.prototype.GetMetadata=m.prototype.GetMetadata=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return V(rd(b,a),Q)};m.prototype.GetAttributeMetadata=m.prototype.GetAttributeMetadata=function(a,c){var b=this.ptr;a&&"object"===
typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return V(Ac(b,a,c),Q)};m.prototype.GetFaceFromMesh=m.prototype.GetFaceFromMesh=function(a,c,e){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);e&&"object"===typeof e&&(e=e.ptr);return!!Zc(b,a,c,e)};m.prototype.GetTriangleStripsFromMesh=m.prototype.GetTriangleStripsFromMesh=function(a,c){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);return Ec(b,a,c)};m.prototype.GetAttributeFloat=
m.prototype.GetAttributeFloat=function(a,c,e){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);e&&"object"===typeof e&&(e=e.ptr);return!!Rb(b,a,c,e)};m.prototype.GetAttributeFloatForAllPoints=m.prototype.GetAttributeFloatForAllPoints=function(a,c,e){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);e&&"object"===typeof e&&(e=e.ptr);return!!Tb(b,a,c,e)};m.prototype.GetAttributeIntForAllPoints=m.prototype.GetAttributeIntForAllPoints=
function(a,c,e){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);c&&"object"===typeof c&&(c=c.ptr);e&&"object"===typeof e&&(e=e.ptr);return!!Jc(b,a,c,e)};m.prototype.SkipAttributeTransform=m.prototype.SkipAttributeTransform=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);Hc(b,a)};m.prototype.__destroy__=m.prototype.__destroy__=function(){kc(this.ptr)};F.prototype=Object.create(v.prototype);F.prototype.constructor=F;F.prototype.__class__=F;F.__cache__={};a.Mesh=F;F.prototype.num_faces=
F.prototype.num_faces=function(){return ac(this.ptr)};F.prototype.num_attributes=F.prototype.num_attributes=function(){return xc(this.ptr)};F.prototype.num_points=F.prototype.num_points=function(){return rc(this.ptr)};F.prototype.__destroy__=F.prototype.__destroy__=function(){fd(this.ptr)};aa.prototype=Object.create(v.prototype);aa.prototype.constructor=aa;aa.prototype.__class__=aa;aa.__cache__={};a.VoidPtr=aa;aa.prototype.__destroy__=aa.prototype.__destroy__=function(){Oc(this.ptr)};L.prototype=
Object.create(v.prototype);L.prototype.constructor=L;L.prototype.__class__=L;L.__cache__={};a.DracoInt32Array=L;L.prototype.GetValue=L.prototype.GetValue=function(a){var b=this.ptr;a&&"object"===typeof a&&(a=a.ptr);return Rc(b,a)};L.prototype.size=L.prototype.size=function(){return Gc(this.ptr)};L.prototype.__destroy__=L.prototype.__destroy__=function(){qc(this.ptr)};Q.prototype=Object.create(v.prototype);Q.prototype.constructor=Q;Q.prototype.__class__=Q;Q.__cache__={};a.Metadata=Q;Q.prototype.__destroy__=
Q.prototype.__destroy__=function(){gd(this.ptr)};(function(){function b(){a.OK=ld();a.ERROR=Kc();a.IO_ERROR=Cc();a.INVALID_PARAMETER=Mc();a.UNSUPPORTED_VERSION=vd();a.UNKNOWN_VERSION=Vc();a.INVALID_GEOMETRY_TYPE=ec();a.POINT_CLOUD=Zb();a.TRIANGULAR_MESH=Yc();a.ATTRIBUTE_INVALID_TRANSFORM=id();a.ATTRIBUTE_NO_TRANSFORM=cc();a.ATTRIBUTE_QUANTIZATION_TRANSFORM=Ic();a.ATTRIBUTE_OCTAHEDRON_TRANSFORM=lc();a.INVALID=Xb();a.POSITION=Wb();a.NORMAL=sd();a.COLOR=Nc();a.TEX_COORD=Fc();a.GENERIC=od()}a.calledRun?
b():ab.unshift(b)})();if("function"===typeof a.onModuleParsed)a.onModuleParsed();return e};"object"===typeof module&&module.exports&&(module.exports=DracoDecoderModule);

View File

@ -14,9 +14,10 @@
//
'use strict';
// If |dracoDecoderType|.type is set to "js", then DRACOLoader will load the
// Draco JavaScript decoder.
THREE.DRACOLoader = function(manager, dracoDecoderType) {
// |dracoPath| sets the path for the Draco decoder source files. The default
// path is "./". If |dracoDecoderType|.type is set to "js", then DRACOLoader
// will load the Draco JavaScript decoder.
THREE.DRACOLoader = function(dracoPath, dracoDecoderType, manager) {
this.timeLoaded = 0;
this.manager = (manager !== undefined) ? manager :
THREE.DefaultLoadingManager;
@ -26,6 +27,7 @@ THREE.DRACOLoader = function(manager, dracoDecoderType) {
this.dracoDecoderType =
(dracoDecoderType !== undefined) ? dracoDecoderType : {};
this.drawMode = THREE.TrianglesDrawMode;
this.dracoSrcPath = (dracoPath !== undefined) ? dracoPath : './';
THREE.DRACOLoader.loadDracoDecoder(this);
};
@ -399,9 +401,10 @@ THREE.DRACOLoader.loadJavaScriptFile = function(path, onLoadFunc,
}
THREE.DRACOLoader.loadWebAssemblyDecoder = function(dracoDecoder) {
dracoDecoder.dracoDecoderType['wasmBinaryFile'] = '../draco_decoder.wasm';
dracoDecoder.dracoDecoderType['wasmBinaryFile'] =
dracoDecoder.dracoSrcPath + 'draco_decoder.wasm';
var xhr = new XMLHttpRequest();
xhr.open('GET', '../draco_decoder.wasm', true);
xhr.open('GET', dracoDecoder.dracoSrcPath + 'draco_decoder.wasm', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
// draco_wasm_wrapper.js must be loaded before DracoDecoderModule is
@ -421,10 +424,11 @@ THREE.DRACOLoader.loadDracoDecoder = function(dracoDecoder) {
if (typeof WebAssembly !== 'object' ||
dracoDecoder.dracoDecoderType.type === 'js') {
// No WebAssembly support
THREE.DRACOLoader.loadJavaScriptFile('../draco_decoder.js',
null, dracoDecoder);
THREE.DRACOLoader.loadJavaScriptFile(dracoDecoder.dracoSrcPath +
'draco_decoder.js', null, dracoDecoder);
} else {
THREE.DRACOLoader.loadJavaScriptFile('../draco_wasm_wrapper.js',
THREE.DRACOLoader.loadJavaScriptFile(dracoDecoder.dracoSrcPath +
'draco_wasm_wrapper.js',
function (dracoDecoder) {
THREE.DRACOLoader.loadWebAssemblyDecoder(dracoDecoder);
}, dracoDecoder);

View File

@ -29,7 +29,7 @@
<pre id="fileDisplayArea"><pre>
</div>
<script src="https://cdn.rawgit.com/mrdoob/three.js/dev/build/three.min.js"></script>
<script src="../DRACOLoader.js"></script>
<script src="DRACOLoader.js"></script>
<script src="geometry_helper.js"></script>
<script>
'use strict';
@ -41,7 +41,7 @@
createDracoDecoder();
function createDracoDecoder() {
dracoLoader = new THREE.DRACOLoader();
dracoLoader = new THREE.DRACOLoader('../');
}
function switchDecoder() {
@ -53,7 +53,7 @@
dracoDecoderType.type = "wasm";
showDecoder.innerText = "Now using WebAssembly Decoder.";
}
dracoLoader = new THREE.DRACOLoader(undefined, dracoDecoderType);
dracoLoader = new THREE.DRACOLoader('../', dracoDecoderType);
}
var camera, cameraTarget, scene, renderer;

View File

@ -5,23 +5,17 @@
News
=======
### Version 1.0.0 release
The latest version of Draco brings many new enhancements to improve the
development experience:
* Stable API release
* Support for npm Javascript package management
* Javascript based encoder
* Generalized metadata for meshes and point clouds
* Now supporting material properties included along with encoded file
* Improved compression rates:
* 15% better compression on smaller models
* 40% better compression of normals
* Performance improvements (~10% faster encoding, decoding)
* Reduced GPU memory usage:
* Option to store decoded quantized attributes
* Support for triangle strip connectivity on decoded meshes
* iOS 9 Javascript decoder
* Bitstream specification now available
### Version 1.1.0 release
The latest version of Draco brings a number of new compression enhancements for
even smaller models:
* Improved compression
* Up to 40% better compression of normals
* Up to 5% better compression for models with multiple attributes
* Faster decode speeds
* 30% faster decoding for models with multiple attributes for lower compression levels 4 and below
* Note: Decreases compression by 10%.
* Encoding of metadata to .obj (e.g. Draco can preserve material or sub-object names)
* Security fixes
Description
===========

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{
"name": "draco3d",
"version": "1.0.2",
"version": "1.1.0",
"description": "Draco is a library for compressing and decompressing 3D geometric meshes and point clouds. It is intended to improve the storage and transmission of 3D graphics.",
"main": "draco3d.js",
"scripts": {

View File

@ -47,13 +47,13 @@ class GeometryAttribute {
NORMAL,
COLOR,
TEX_COORD,
// Total number of different attribute types.
// Always keep behind all named attributes.
NAMED_ATTRIBUTES_COUNT,
// A special id used to mark attributes that are not assigned to any known
// predefined use case. Such attributes are often used for a shader specific
// data.
GENERIC = NAMED_ATTRIBUTES_COUNT
GENERIC,
// Total number of different attribute types.
// Always keep behind all named attributes.
NAMED_ATTRIBUTES_COUNT,
};
GeometryAttribute();

View File

@ -83,7 +83,7 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
// Update the inverse map.
if (att_id >= static_cast<int32_t>(point_attribute_to_local_id_map_.size()))
point_attribute_to_local_id_map_.resize(att_id + 1, -1);
point_attribute_to_local_id_map_[att_id] = point_attribute_ids_.size() - 1;
point_attribute_to_local_id_map_[att_id] = i;
}
return true;
}

View File

@ -101,8 +101,6 @@ bool MeshPredictionSchemeGeometricNormalDecoder<
// Expecting in_data in octahedral coordinates, i.e., portable attribute.
DCHECK_EQ(num_components, 2);
flip_normal_bit_decoder_.EndDecoding();
const int corner_map_size = this->mesh_data().data_to_corner_map()->size();
VectorD<int32_t, 3> pred_normal_3d;
@ -126,6 +124,7 @@ bool MeshPredictionSchemeGeometricNormalDecoder<
this->transform().ComputeOriginalValue(
pred_normal_oct, in_corr + data_offset, out_data + data_offset);
}
flip_normal_bit_decoder_.EndDecoding();
return true;
}
@ -139,7 +138,9 @@ bool MeshPredictionSchemeGeometricNormalDecoder<
uint8_t prediction_mode;
buffer->Decode(&prediction_mode);
if (prediction_mode)
if (!predictor_.SetNormalPredictionMode(
NormalPredictionMode(prediction_mode)))
return false;
// Init normal flips.

View File

@ -163,7 +163,7 @@ bool MeshPredictionSchemeGeometricNormalEncoder<
if (!this->transform().EncodeTransformData(buffer))
return false;
const uint8_t prediction_mode = 0;
const uint8_t prediction_mode = predictor_.GetNormalPredictionMode();
if (!buffer->Encode(prediction_mode))
return false;

View File

@ -31,12 +31,14 @@ class MeshPredictionSchemeGeometricNormalPredictorArea
public:
MeshPredictionSchemeGeometricNormalPredictorArea(const MeshDataT &md)
: Base(md){};
: Base(md) {
this->SetNormalPredictionMode(TRIANGLE_AREA);
};
virtual ~MeshPredictionSchemeGeometricNormalPredictorArea() {}
// Computes predicted octahedral coordinates on a given corner.
virtual void ComputePredictedValue(CornerIndex corner_id,
DataTypeT *prediction) override {
void ComputePredictedValue(CornerIndex corner_id,
DataTypeT *prediction) override {
DCHECK(this->IsInitialized());
typedef typename MeshDataT::CornerTable CornerTable;
const CornerTable *const corner_table = this->mesh_data_.corner_table();
@ -48,36 +50,59 @@ class MeshPredictionSchemeGeometricNormalPredictorArea
// Computing normals for triangles and adding them up.
VectorD<int64_t, 3> normal;
CornerIndex c_next, c_prev;
while (!cit.End()) {
// Getting corners.
const CornerIndex c_next = corner_table->Next(corner_id);
const CornerIndex c_prev = corner_table->Previous(corner_id);
// Getting positions for next and previous.
const auto pos_next = this->GetPositionForCorner(c_next);
const auto pos_prev = this->GetPositionForCorner(c_prev);
if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
c_next = corner_table->Next(corner_id);
c_prev = corner_table->Previous(corner_id);
} else {
c_next = corner_table->Next(cit.Corner());
c_prev = corner_table->Previous(cit.Corner());
}
const VectorD<int64_t, 3> pos_next = this->GetPositionForCorner(c_next);
const VectorD<int64_t, 3> pos_prev = this->GetPositionForCorner(c_prev);
// Computing delta vectors to next and prev.
const auto delta_next = pos_next - pos_cent;
const auto delta_prev = pos_prev - pos_cent;
const VectorD<int64_t, 3> delta_next = pos_next - pos_cent;
const VectorD<int64_t, 3> delta_prev = pos_prev - pos_cent;
// Computing cross product.
const auto cross = CrossProduct(delta_next, delta_prev);
const VectorD<int64_t, 3> cross = CrossProduct(delta_next, delta_prev);
normal = normal + cross;
cit.Next();
}
// Convert to int32_t, make sure entries are not too large.
const int32_t abs_sum = normal.AbsSum();
constexpr int64_t upper_bound = 1 << 29;
if (abs_sum > upper_bound) {
const int64_t quotient = abs_sum / upper_bound;
normal = normal / quotient;
if (this->normal_prediction_mode_ == ONE_TRIANGLE) {
const int32_t abs_sum = normal.AbsSum();
if (abs_sum > upper_bound) {
const int64_t quotient = abs_sum / upper_bound;
normal = normal / quotient;
}
} else {
const int64_t abs_sum = normal.AbsSum();
if (abs_sum > upper_bound) {
const int64_t quotient = abs_sum / upper_bound;
normal = normal / quotient;
}
}
DCHECK_LE(normal.AbsSum(), upper_bound);
prediction[0] = static_cast<int32_t>(normal[0]);
prediction[1] = static_cast<int32_t>(normal[1]);
prediction[2] = static_cast<int32_t>(normal[2]);
}
bool SetNormalPredictionMode(NormalPredictionMode mode) override {
if (mode == ONE_TRIANGLE) {
this->normal_prediction_mode_ = mode;
return true;
} else if (mode == TRIANGLE_AREA) {
this->normal_prediction_mode_ = mode;
return true;
}
return false;
}
};
} // namespace draco

View File

@ -19,6 +19,7 @@
#include "draco/attributes/point_attribute.h"
#include "draco/compression/attributes/normal_compression_utils.h"
#include "draco/compression/config/compression_shared.h"
#include "draco/core/math_utils.h"
#include "draco/core/vector_d.h"
#include "draco/mesh/corner_table.h"
@ -51,6 +52,11 @@ class MeshPredictionSchemeGeometricNormalPredictorBase {
return true;
}
virtual bool SetNormalPredictionMode(NormalPredictionMode mode) = 0;
virtual NormalPredictionMode GetNormalPredictionMode() const {
return normal_prediction_mode_;
}
protected:
VectorD<int64_t, 3> GetPositionForDataId(int data_id) const {
DCHECK(this->IsInitialized());
@ -80,6 +86,7 @@ class MeshPredictionSchemeGeometricNormalPredictorBase {
const PointAttribute *pos_attribute_;
const PointIndex *entry_to_point_id_map_;
MeshDataT mesh_data_;
NormalPredictionMode normal_prediction_mode_;
};
} // namespace draco

View File

@ -268,8 +268,16 @@ void MeshPredictionSchemeTexCoordsDecoder<DataTypeT, TransformT, MeshDataT>::
if (std::is_integral<DataTypeT>::value) {
// Round the predicted value for integer types.
predicted_value_[0] = static_cast<int>(floor(predicted_uv[0] + 0.5));
predicted_value_[1] = static_cast<int>(floor(predicted_uv[1] + 0.5));
if (std::isnan(predicted_uv[0])) {
predicted_value_[0] = INT_MIN;
} else {
predicted_value_[0] = static_cast<int>(floor(predicted_uv[0] + 0.5));
}
if (std::isnan(predicted_uv[1])) {
predicted_value_[1] = INT_MIN;
} else {
predicted_value_[1] = static_cast<int>(floor(predicted_uv[1] + 0.5));
}
} else {
predicted_value_[0] = static_cast<int>(predicted_uv[0]);
predicted_value_[1] = static_cast<int>(predicted_uv[1]);

View File

@ -103,10 +103,17 @@ bool SequentialIntegerAttributeDecoder::DecodeIntegerValues(
if (!in_buffer->Decode(&num_bytes))
return false;
if (num_bytes == DataTypeLength(DT_INT32)) {
if (portable_attribute()->buffer()->data_size() <
sizeof(int32_t) * num_values)
return false;
if (!in_buffer->Decode(portable_attribute_data,
sizeof(int32_t) * num_values))
return false;
} else {
if (portable_attribute()->buffer()->data_size() < num_bytes * num_values)
return false;
if (in_buffer->remaining_size() < num_bytes * num_values)
return false;
for (uint32_t i = 0; i < num_values; ++i) {
in_buffer->Decode(portable_attribute_data + i, num_bytes);
}

View File

@ -21,7 +21,7 @@ namespace draco {
// Latest Draco bit-stream version.
static constexpr uint8_t kDracoBitstreamVersionMajor = 2;
static constexpr uint8_t kDracoBitstreamVersionMinor = 0;
static constexpr uint8_t kDracoBitstreamVersionMinor = 1;
// Macro that converts the Draco bit-stream into one uint16_t number.
// Useful mostly when checking version numbers.
@ -120,6 +120,11 @@ struct DracoHeader {
uint16_t flags;
};
enum NormalPredictionMode {
ONE_TRIANGLE = 0, // To be deprecated.
TRIANGLE_AREA = 1,
};
// Mask for setting and getting the bit for metadata in |flags| of header.
#define METADATA_FLAG_MASK 0x8000

View File

@ -68,6 +68,8 @@ class DracoOptions {
bool default_val) const;
void SetAttributeBool(const AttributeKey &att_key, const std::string &name,
bool val);
bool IsAttributeOptionSet(const AttributeKey &att_key,
const std::string &name) const;
// Gets/sets a global option that is not specific to any attribute.
int GetGlobalInt(const std::string &name, int default_val) const {
@ -82,6 +84,9 @@ class DracoOptions {
void SetGlobalBool(const std::string &name, bool val) {
global_options_.SetBool(name, val);
}
bool IsGlobalOptionSet(const std::string &name) const {
return global_options_.IsOptionSet(name);
}
// Sets or replaces attribute options with the provided |options|.
void SetAttributeOptions(const AttributeKey &att_key, const Options &options);
@ -156,6 +161,15 @@ void DracoOptions<AttributeKeyT>::SetAttributeBool(const AttributeKeyT &att_key,
GetAttributeOptions(att_key)->SetBool(name, val);
}
template <typename AttributeKeyT>
bool DracoOptions<AttributeKeyT>::IsAttributeOptionSet(
const AttributeKey &att_key, const std::string &name) const {
const Options *const att_options = FindAttributeOptions(att_key);
if (att_options)
return att_options->IsOptionSet(name);
return global_options_.IsOptionSet(name);
}
template <typename AttributeKeyT>
void DracoOptions<AttributeKeyT>::SetAttributeOptions(
const AttributeKey &att_key, const Options &options) {

View File

@ -43,7 +43,6 @@ namespace draco {
template <class TraversalDecoder>
MeshEdgeBreakerDecoderImpl<TraversalDecoder>::MeshEdgeBreakerDecoderImpl()
: decoder_(nullptr),
num_processed_hole_events_(0),
last_symbol_id_(-1),
last_vert_id_(-1),
last_face_id_(-1),
@ -264,7 +263,6 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
init_face_configurations_.clear();
init_corners_.clear();
num_processed_hole_events_ = 0;
last_symbol_id_ = -1;
last_face_id_ = -1;
@ -352,9 +350,16 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
// Decode connectivity of non-position attributes.
if (attribute_data_.size() > 0) {
for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
if (!DecodeAttributeConnectivitiesOnFace(ci))
return false;
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
if (!DecodeAttributeConnectivitiesOnFaceLegacy(ci))
return false;
}
} else {
for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
if (!DecodeAttributeConnectivitiesOnFace(ci))
return false;
}
}
}
traversal_decoder_.Done();
@ -761,11 +766,11 @@ MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
}
}
}
uint32_t num_hole_events;
uint32_t num_hole_events = 0;
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
if (!decoder_buffer->Decode(&num_hole_events))
return -1;
} else {
} else if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 1)) {
if (!DecodeVarint(&num_hole_events, decoder_buffer))
return -1;
}
@ -794,8 +799,8 @@ MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
}
template <class TraversalDecoder>
bool MeshEdgeBreakerDecoderImpl<
TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) {
bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::
DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner) {
// Three corners of the face.
const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
corner_table_->Previous(corner)};
@ -820,6 +825,38 @@ bool MeshEdgeBreakerDecoderImpl<
return true;
}
template <class TraversalDecoder>
bool MeshEdgeBreakerDecoderImpl<
TraversalDecoder>::DecodeAttributeConnectivitiesOnFace(CornerIndex corner) {
// Three corners of the face.
const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
corner_table_->Previous(corner)};
const FaceIndex src_face_id = corner_table_->Face(corner);
for (int c = 0; c < 3; ++c) {
const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
if (opp_corner < 0) {
// Don't decode attribute seams on boundary edges (every boundary edge
// is automatically an attribute seam).
for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
}
continue;
}
const FaceIndex opp_face_id = corner_table_->Face(opp_corner);
// Don't decode edges when the opposite face has been already processed.
if (opp_face_id < src_face_id)
continue;
for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
const bool is_seam = traversal_decoder_.DecodeAttributeSeam(i);
if (is_seam)
attribute_data_[i].attribute_seam_corners.push_back(corners[c].value());
}
}
return true;
}
template <class TraversalDecoder>
bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::AssignPointsToCorners() {
// Map between the existing and deduplicated point ids.

View File

@ -111,6 +111,7 @@ class MeshEdgeBreakerDecoderImpl : public MeshEdgeBreakerDecoderImplInterface {
// Decodes all non-position attribute connectivity on the currently
// processed face.
bool DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner);
bool DecodeAttributeConnectivitiesOnFace(CornerIndex corner);
// Initializes mapping between corners and point ids.
@ -149,9 +150,6 @@ class MeshEdgeBreakerDecoderImpl : public MeshEdgeBreakerDecoderImplInterface {
// List of decoded hole events.
std::vector<HoleEventData> hole_event_data_;
// The number of processed hole events.
int num_processed_hole_events_;
// Configuration of the initial face for each mesh component.
std::vector<bool> init_face_configurations_;

View File

@ -38,7 +38,8 @@ MeshEdgeBreakerEncoderImpl<TraversalEncoder>::MeshEdgeBreakerEncoderImpl()
: encoder_(nullptr),
mesh_(nullptr),
last_encoded_symbol_id_(-1),
num_split_symbols_(0) {}
num_split_symbols_(0),
use_single_connectivity_(false) {}
template <class TraversalEncoder>
bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::Init(
@ -46,6 +47,16 @@ bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::Init(
encoder_ = encoder;
mesh_ = encoder->mesh();
attribute_encoder_to_data_id_map_.clear();
if (encoder_->options()->IsGlobalOptionSet("split_mesh_on_seams")) {
use_single_connectivity_ =
encoder_->options()->GetGlobalBool("split_mesh_on_seams", false);
} else if (encoder_->options()->GetSpeed() >= 6) {
// Else use default setting based on speed.
use_single_connectivity_ = true;
} else {
use_single_connectivity_ = false;
}
return true;
}
@ -101,9 +112,16 @@ MeshEdgeBreakerEncoderImpl<TraversalEncoder>::CreateVertexTraversalSequencer(
template <class TraversalEncoder>
bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::GenerateAttributesEncoder(
int32_t att_id) {
// For now, create one encoder for each attribute. Ideally we can share
// the same encoder for attributes with the same connectivity (this is
// especially true for per-vertex attributes).
// For now, either create one encoder for each attribute or use a single
// encoder for all attributes. Ideally we can share the same encoder for
// a sub-set of attributes with the same connectivity (this is especially true
// for per-vertex attributes).
if (use_single_connectivity_ && GetEncoder()->num_attributes_encoders() > 0) {
// We are using single connectivity and we already have an attribute
// encoder. Add the attribute to the encoder and return.
GetEncoder()->attributes_encoder(0)->AddAttributeId(att_id);
return true;
}
const int32_t element_type =
GetEncoder()->mesh()->GetAttributeElementType(att_id);
const PointAttribute *const att =
@ -117,7 +135,8 @@ bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::GenerateAttributesEncoder(
}
MeshTraversalMethod traversal_method = MESH_TRAVERSAL_DEPTH_FIRST;
std::unique_ptr<PointsSequencer> sequencer;
if (att->attribute_type() == GeometryAttribute::POSITION ||
if (use_single_connectivity_ ||
att->attribute_type() == GeometryAttribute::POSITION ||
element_type == MESH_VERTEX_ATTRIBUTE ||
(element_type == MESH_CORNER_ATTRIBUTE &&
attribute_data_[att_data_id].connectivity_data.no_interior_seams())) {
@ -127,20 +146,30 @@ bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::GenerateAttributesEncoder(
typedef MeshAttributeIndicesEncodingObserver<CornerTable> AttObserver;
MeshAttributeIndicesEncodingData *encoding_data;
if (att->attribute_type() == GeometryAttribute::POSITION) {
if (use_single_connectivity_ ||
att->attribute_type() == GeometryAttribute::POSITION) {
encoding_data = &pos_encoding_data_;
} else {
encoding_data = &attribute_data_[att_data_id].encoding_data;
attribute_data_[att_data_id].is_connectivity_used = false;
}
if (att->attribute_type() == GeometryAttribute::POSITION &&
GetEncoder()->options()->GetSpeed() == 0) {
if (GetEncoder()->options()->GetSpeed() == 0 &&
att->attribute_type() == GeometryAttribute::POSITION) {
traversal_method = MESH_TRAVERSAL_PREDICTION_DEGREE;
if (use_single_connectivity_ && mesh_->num_attributes() > 1) {
// Make sure we don't use the prediction degree traversal when we encode
// multiple attributes using the same connectivity.
// TODO(ostava): We should investigate this and see if the prediction
// degree can be actually used efficiently for non-position attributes.
traversal_method = MESH_TRAVERSAL_DEPTH_FIRST;
}
}
if (traversal_method == MESH_TRAVERSAL_PREDICTION_DEGREE) {
// Traverser that is used to generate the encoding order of each
// attribute.
typedef PredictionDegreeTraverser<AttProcessor, AttObserver> AttTraverser;
sequencer = CreateVertexTraversalSequencer<AttTraverser>(encoding_data);
traversal_method = MESH_TRAVERSAL_PREDICTION_DEGREE;
} else {
// Traverser that is used to generate the encoding order of each
// attribute.
@ -230,8 +259,14 @@ bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
// To encode the mesh, we need face connectivity data stored in a corner
// table. To compute the connectivity we must use indices associated with
// POSITION attribute, because they define which edges can be connected
// together.
corner_table_ = CreateCornerTable(mesh_);
// together, unless the option |use_single_connectivity_| is set in which case
// we break the mesh along attribute seams and use the same connectivity for
// all attributes.
if (use_single_connectivity_) {
corner_table_ = CreateCornerTableFromAllAttributes(mesh_);
} else {
corner_table_ = CreateCornerTable(mesh_);
}
if (corner_table_ == nullptr) {
// Failed to construct the corner table.
return false;
@ -274,7 +309,6 @@ bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
face_to_split_symbol_map_.clear();
visited_holes_.clear();
vertex_hole_id_.assign(corner_table_->num_vertices(), -1);
hole_event_data_.clear();
processed_connectivity_corners_.clear();
processed_connectivity_corners_.reserve(corner_table_->num_faces());
pos_encoding_data_.num_values = 0;
@ -287,6 +321,7 @@ bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
const int8_t num_attribute_data = attribute_data_.size();
encoder_->buffer()->Encode(num_attribute_data);
traversal_encoder_.SetNumAttributeData(num_attribute_data);
const int num_corners = corner_table_->num_corners();
@ -361,6 +396,7 @@ bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
// Encode connectivity for all non-position attributes.
if (attribute_data_.size() > 0) {
// Use the same order of corner that will be used by the decoder.
visited_faces_.assign(mesh_->num_faces(), false);
for (CornerIndex ci : processed_connectivity_corners_) {
EncodeAttributeConnectivitiesOnFace(ci);
}
@ -413,19 +449,6 @@ bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::EncodeConnectivity() {
}
encoder_->buffer()->EndBitEncoding();
}
// Encode hole events data.
num_events = hole_event_data_.size();
EncodeVarint(num_events, encoder_->buffer());
if (num_events > 0) {
// Encode hole symbol ids using delta and varint coding. The symbol ids are
// always stored in increasing order so the deltas are going to be positive.
int last_symbol_id = 0;
for (uint32_t i = 0; i < num_events; ++i) {
EncodeVarint<uint32_t>(hole_event_data_[i].symbol_id - last_symbol_id,
encoder_->buffer());
last_symbol_id = hole_event_data_[i].symbol_id;
}
}
return true;
}
@ -552,8 +575,6 @@ bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::EncodeConnectivityFromCorner(
const int hole_id = vertex_hole_id_[vert_id.value()];
if (!visited_holes_[hole_id]) {
EncodeHole(corner_id, false);
hole_event_data_.push_back(
HoleEventData(last_encoded_symbol_id_));
}
}
face_to_split_symbol_map_[face_id.value()] = last_encoded_symbol_id_;
@ -732,6 +753,9 @@ void MeshEdgeBreakerEncoderImpl<
template <class TraversalEncoder>
bool MeshEdgeBreakerEncoderImpl<TraversalEncoder>::InitAttributeData() {
if (use_single_connectivity_)
return true; // All attributes use the same connectivity.
const int num_attributes = mesh_->num_attributes();
// Ignore the position attribute. It's decoded separately.
attribute_data_.resize(num_attributes - 1);
@ -773,10 +797,16 @@ bool MeshEdgeBreakerEncoderImpl<
const CornerIndex corners[3] = {corner, corner_table_->Next(corner),
corner_table_->Previous(corner)};
const FaceIndex src_face_id = corner_table_->Face(corner);
visited_faces_[src_face_id.value()] = true;
for (int c = 0; c < 3; ++c) {
const CornerIndex opp_corner = corner_table_->Opposite(corners[c]);
if (opp_corner < 0)
continue; // Don't encode attribute seams on boundary edges.
const FaceIndex opp_face_id = corner_table_->Face(opp_corner);
// Don't encode edges when the opposite face has been already processed.
if (visited_faces_[opp_face_id.value()])
continue;
for (uint32_t i = 0; i < attribute_data_.size(); ++i) {
if (attribute_data_[i].connectivity_data.IsCornerOppositeToSeamEdge(

View File

@ -164,9 +164,6 @@ class MeshEdgeBreakerEncoderImpl : public MeshEdgeBreakerEncoderImplInterface {
// Array for mapping vertices to hole ids. If a vertex is not on a hole, the
// stored value is -1.
std::vector<int> vertex_hole_id_;
// Array of hole events encountered during the traversal. There will be always
// exactly one hole event for each hole in the input mesh.
std::vector<HoleEventData> hole_event_data_;
// Id of the last encoded symbol.
int last_encoded_symbol_id_;
@ -194,6 +191,13 @@ class MeshEdgeBreakerEncoderImpl : public MeshEdgeBreakerEncoderImplInterface {
std::vector<int32_t> attribute_encoder_to_data_id_map_;
TraversalEncoderT traversal_encoder_;
// If set, the encoder is going to use the same connectivity for all
// attributes. This effectively breaks the mesh along all attribute seams.
// In general, this approach should be much faster compared to encoding each
// connectivity separately, but the decoded model may contain higher number of
// duplicate attribute values which may decrease the compression ratio.
bool use_single_connectivity_;
};
} // namespace draco

View File

@ -150,4 +150,43 @@ TEST_F(MeshEdgebreakerEncodingTest, TestDecoderReuse) {
<< "Decoded meshes are not the same";
}
TEST_F(MeshEdgebreakerEncodingTest, TestSingleConnectivityEncoding) {
// Tests whether the edgebreaker method successfully encodes a mesh with
// multiple attributes using single connectivity by breaking the mesh along
// attribute seams.
const std::string file_name = "cube_att.obj";
const std::string path = GetTestFileFullPath(file_name);
const std::unique_ptr<Mesh> mesh(ReadMeshFromFile(path));
ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name;
for (int i = 0; i < 2; ++i) {
// Set the option to enable/disable single connectivity encoding.
EncoderOptionsBase<GeometryAttribute::Type> options =
EncoderOptionsBase<GeometryAttribute::Type>::CreateDefaultOptions();
options.SetGlobalBool("split_mesh_on_seams", i == 0 ? true : false);
EncoderBuffer buffer;
draco::Encoder encoder;
encoder.Reset(options);
encoder.SetSpeedOptions(0, 0);
encoder.SetAttributeQuantization(GeometryAttribute::POSITION, 8);
encoder.SetAttributeQuantization(GeometryAttribute::TEX_COORD, 8);
encoder.SetAttributeQuantization(GeometryAttribute::NORMAL, 8);
encoder.SetEncodingMethod(MESH_EDGEBREAKER_ENCODING);
ASSERT_TRUE(encoder.EncodeMeshToBuffer(*mesh, &buffer).ok());
DecoderBuffer dec_buffer;
dec_buffer.Init(buffer.data(), buffer.size());
Decoder decoder;
auto dec_mesh = decoder.DecodeMeshFromBuffer(&dec_buffer).value();
ASSERT_NE(dec_mesh, nullptr);
ASSERT_EQ(dec_mesh->num_points(), 24);
ASSERT_EQ(dec_mesh->num_attributes(), 3);
ASSERT_EQ(dec_mesh->attribute(0)->size(), i == 0 ? 24 : 8);
ASSERT_EQ(dec_mesh->attribute(1)->size(), 24);
ASSERT_EQ(dec_mesh->attribute(2)->size(), 24);
}
}
} // namespace draco

View File

@ -31,24 +31,30 @@ typedef RAnsBitEncoder BinaryEncoder;
class MeshEdgeBreakerTraversalEncoder {
public:
MeshEdgeBreakerTraversalEncoder()
: encoder_impl_(nullptr), attribute_connectivity_encoders_(nullptr) {}
: encoder_impl_(nullptr),
attribute_connectivity_encoders_(nullptr),
num_attribute_data_(0) {}
bool Init(MeshEdgeBreakerEncoderImplInterface *encoder) {
encoder_impl_ = encoder;
return true;
}
// Set the number of non-position attribute data for which we need to encode
// the connectivity.
void SetNumAttributeData(int num_data) { num_attribute_data_ = num_data; }
// Called before the traversal encoding is started.
void Start() {
const Mesh *const mesh = encoder_impl_->GetEncoder()->mesh();
// Allocate enough storage to store initial face configurations. This can
// consume at most 1 bit per face if all faces are isolated.
start_face_buffer_.StartBitEncoding(mesh->num_faces(), true);
if (mesh->num_attributes() > 1) {
if (num_attribute_data_ > 0) {
// Init and start arithmetic encoders for storing configuration types
// of non-position attributes.
attribute_connectivity_encoders_ = std::unique_ptr<BinaryEncoder[]>(
new BinaryEncoder[mesh->num_attributes() - 1]);
for (int i = 0; i < mesh->num_attributes() - 1; ++i) {
new BinaryEncoder[num_attribute_data_]);
for (int i = 0; i < num_attribute_data_; ++i) {
attribute_connectivity_encoders_[i].StartEncoding();
}
}
@ -92,8 +98,7 @@ class MeshEdgeBreakerTraversalEncoder {
traversal_buffer_.Encode(start_face_buffer_.data(),
start_face_buffer_.size());
if (attribute_connectivity_encoders_ != nullptr) {
const Mesh *const mesh = encoder_impl_->GetEncoder()->mesh();
for (int i = 0; i < mesh->num_attributes() - 1; ++i) {
for (int i = 0; i < num_attribute_data_; ++i) {
attribute_connectivity_encoders_[i].EndEncoding(&traversal_buffer_);
}
}
@ -120,6 +125,7 @@ class MeshEdgeBreakerTraversalEncoder {
// Arithmetic encoder for encoding attribute seams.
// One context for each non-position attribute.
std::unique_ptr<BinaryEncoder[]> attribute_connectivity_encoders_;
int num_attribute_data_;
};
} // namespace draco

View File

@ -63,12 +63,13 @@ TEST_P(MeshEncoderTest, EncodeGoldenMesh) {
std::string golden_file_name = file_name;
golden_file_name += '.';
golden_file_name += GetParam();
golden_file_name += ".1.0.0.drc";
golden_file_name += ".1.1.0.drc";
const std::unique_ptr<Mesh> mesh(DecodeObj(file_name));
ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name;
ExpertEncoder encoder(*mesh.get());
encoder.SetEncodingMethod(method);
encoder.SetAttributeQuantization(0, 20);
EncoderBuffer buffer;
ASSERT_TRUE(encoder.EncodeToBuffer(&buffer).ok())
<< "Failed encoding test mesh " << file_name << " with method "

View File

@ -172,7 +172,7 @@ static inline int rabs_desc_read(struct AnsDecoder *ans, AnsP8 p0) {
unsigned quot, rem, x, xn;
#endif
const AnsP8 p = ans_p8_precision - p0;
if (ans->state < l_base) {
if (ans->state < l_base && ans->buf_offset > 0) {
ans->state = ans->state * io_base + ans->buf[--ans->buf_offset];
}
#if ANS_IMPL1

View File

@ -18,7 +18,7 @@
namespace draco {
// Draco version is comprised of <major>.<minor>.<revision>.
static const char kDracoVersion[] = "1.0.1";
static const char kDracoVersion[] = "1.1.0";
const char *Version() { return kDracoVersion; }

View File

@ -29,7 +29,7 @@ ObjDecoder::ObjDecoder()
num_positions_(0),
num_tex_coords_(0),
num_normals_(0),
num_sub_objects_(0),
last_sub_obj_id_(0),
pos_att_id_(-1),
tex_att_id_(-1),
norm_att_id_(-1),
@ -37,7 +37,6 @@ ObjDecoder::ObjDecoder()
sub_obj_att_id_(-1),
deduplicate_input_values_(true),
last_material_id_(0),
open_material_file_(false),
use_metadata_(false),
out_mesh_(nullptr),
out_point_cloud_(nullptr) {}
@ -65,7 +64,6 @@ bool ObjDecoder::DecodeFromFile(const std::string &file_name,
buffer_.Init(&data[0], file_size);
out_point_cloud_ = out_point_cloud;
open_material_file_ = true;
input_file_name_ = file_name;
return DecodeInternal();
}
@ -79,7 +77,6 @@ bool ObjDecoder::DecodeFromBuffer(DecoderBuffer *buffer,
PointCloud *out_point_cloud) {
out_point_cloud_ = out_point_cloud;
buffer_.Init(buffer->data_head(), buffer->remaining_size());
open_material_file_ = false;
return DecodeInternal();
}
@ -91,7 +88,7 @@ bool ObjDecoder::DecodeInternal() {
counting_mode_ = true;
ResetCounters();
material_name_to_id_.clear();
num_sub_objects_ = 0;
last_sub_obj_id_ = 0;
// Parse all lines.
bool error = false;
while (ParseDefinition(&error) && !error) {
@ -156,22 +153,24 @@ bool ObjDecoder::DecodeInternal() {
const AttributeValueIndex i(itr.second);
material_metadata->AddEntryInt(itr.first, itr.second);
}
material_metadata->AddEntryString("file_name", material_file_name_);
if (!material_file_name_.empty()) {
material_metadata->AddEntryString("file_name", material_file_name_);
}
out_point_cloud_->AddAttributeMetadata(std::move(material_metadata));
}
}
if (num_sub_objects_ > 1) {
if (!obj_name_to_id_.empty()) {
GeometryAttribute va;
if (num_sub_objects_ < 256) {
if (obj_name_to_id_.size() < 256) {
va.Init(GeometryAttribute::GENERIC, nullptr, 1, DT_UINT8, false, 1, 0);
} else if (num_sub_objects_ < (1 << 16)) {
} else if (obj_name_to_id_.size() < (1 << 16)) {
va.Init(GeometryAttribute::GENERIC, nullptr, 1, DT_UINT16, false, 2, 0);
} else {
va.Init(GeometryAttribute::GENERIC, nullptr, 1, DT_UINT32, false, 4, 0);
}
sub_obj_att_id_ =
out_point_cloud_->AddAttribute(va, false, num_sub_objects_);
out_point_cloud_->AddAttribute(va, false, obj_name_to_id_.size());
// Fill the sub object id entries.
for (const auto &itr : obj_name_to_id_) {
const AttributeValueIndex i(itr.second);
@ -224,7 +223,7 @@ void ObjDecoder::ResetCounters() {
num_tex_coords_ = 0;
num_normals_ = 0;
last_material_id_ = 0;
num_sub_objects_ = 0;
last_sub_obj_id_ = 0;
}
bool ObjDecoder::ParseDefinition(bool *error) {
@ -419,9 +418,6 @@ bool ObjDecoder::ParseMaterialLib(bool *error) {
// Allow only one material library per file for now.
if (material_name_to_id_.size() > 0)
return false;
// Skip the parsing if we don't want to open material files.
if (!open_material_file_)
return false;
std::array<char, 6> c;
if (!buffer()->Peek(&c)) {
return false;
@ -447,10 +443,9 @@ bool ObjDecoder::ParseMaterialLib(bool *error) {
}
bool ObjDecoder::ParseMaterial(bool * /* error */) {
if (counting_mode_)
return false; // Skip when we are counting definitions.
if (material_att_id_ < 0)
return false; // Don't parse it when we don't use materials.
// In second pass, skip when we don't use materials.
if (!counting_mode_ && material_att_id_ < 0)
return false;
std::array<char, 6> c;
if (!buffer()->Peek(&c)) {
return false;
@ -464,7 +459,11 @@ bool ObjDecoder::ParseMaterial(bool * /* error */) {
return false;
auto it = material_name_to_id_.find(mat_name);
if (it == material_name_to_id_.end()) {
// Invalid material..ignore.
// In first pass, materials found in obj that's not in the .mtl file
// will be added to the list.
const size_t num_mat = material_name_to_id_.size();
material_name_to_id_[mat_name] = num_mat;
last_material_id_ = num_mat;
return true;
}
last_material_id_ = it->second;
@ -485,10 +484,11 @@ bool ObjDecoder::ParseObject(bool *error) {
return false;
auto it = obj_name_to_id_.find(obj_name);
if (it == obj_name_to_id_.end()) {
obj_name_to_id_[obj_name] = num_sub_objects_;
num_sub_objects_++;
const int num_obj = obj_name_to_id_.size();
obj_name_to_id_[obj_name] = num_obj;
last_sub_obj_id_ = num_obj;
} else {
num_sub_objects_ = it->second + 1;
last_sub_obj_id_ = it->second;
}
return true;
}
@ -584,9 +584,8 @@ void ObjDecoder::MapPointToVertexIndices(
// Assign sub-object index to the point if it is available.
if (sub_obj_att_id_ >= 0) {
const int sub_obj_id = num_sub_objects_ > 0 ? num_sub_objects_ - 1 : 0;
out_point_cloud_->attribute(sub_obj_att_id_)
->SetPointMapEntry(vert_id, AttributeValueIndex(sub_obj_id));
->SetPointMapEntry(vert_id, AttributeValueIndex(last_sub_obj_id_));
}
}
@ -642,8 +641,7 @@ bool ObjDecoder::ParseMaterialFileDefinition(bool * /* error */) {
return false;
if (str.compare("newmtl") == 0) {
parser::SkipWhitespace(buffer());
if (!parser::ParseString(buffer(), &str))
return false;
parser::ParseLine(buffer(), &str);
// Add new material to our map.
const size_t material_name_id = material_name_to_id_.size();
material_name_to_id_[str] = material_name_id;

View File

@ -93,7 +93,7 @@ class ObjDecoder {
int num_positions_;
int num_tex_coords_;
int num_normals_;
int num_sub_objects_;
int last_sub_obj_id_;
int pos_att_id_;
int tex_att_id_;
@ -106,7 +106,6 @@ class ObjDecoder {
int last_material_id_;
std::string material_file_name_;
bool open_material_file_;
std::string input_file_name_;
std::unordered_map<std::string, int> material_name_to_id_;

View File

@ -16,15 +16,21 @@
#include <fstream>
#include "draco/metadata/geometry_metadata.h"
namespace draco {
ObjEncoder::ObjEncoder()
: pos_att_(nullptr),
tex_coord_att_(nullptr),
normal_att_(nullptr),
material_att_(nullptr),
sub_obj_att_(nullptr),
out_buffer_(nullptr),
in_point_cloud_(nullptr),
in_mesh_(nullptr) {}
in_mesh_(nullptr),
current_sub_obj_id_(-1),
current_material_id_(-1) {}
bool ObjEncoder::EncodeToFile(const PointCloud &pc,
const std::string &file_name) {
@ -63,6 +69,14 @@ bool ObjEncoder::EncodeInternal() {
pos_att_ = nullptr;
tex_coord_att_ = nullptr;
normal_att_ = nullptr;
material_att_ = nullptr;
sub_obj_att_ = nullptr;
current_sub_obj_id_ = -1;
current_material_id_ = -1;
if (!GetSubObjects())
return false;
if (!EncodeMaterialFileName())
return false;
if (!EncodePositions())
return false;
if (!EncodeTextureCoordinates())
@ -81,9 +95,66 @@ bool ObjEncoder::ExitAndCleanup(bool return_value) {
pos_att_ = nullptr;
tex_coord_att_ = nullptr;
normal_att_ = nullptr;
material_att_ = nullptr;
sub_obj_att_ = nullptr;
current_sub_obj_id_ = -1;
current_material_id_ = -1;
return return_value;
}
bool ObjEncoder::GetSubObjects() {
const GeometryMetadata *pc_metadata = in_point_cloud_->GetMetadata();
if (!pc_metadata)
return true;
const AttributeMetadata *sub_obj_metadata =
pc_metadata->GetAttributeMetadataByStringEntry("name", "sub_obj");
if (!sub_obj_metadata)
return true;
sub_obj_id_to_name_.clear();
for (const auto &entry : sub_obj_metadata->entries()) {
// Sub-object id must be int.
int value = 0;
if (!entry.second.GetValue(&value))
continue;
sub_obj_id_to_name_[value] = entry.first;
}
const int sub_obj_att_id = sub_obj_metadata->attribute_id();
sub_obj_att_ = in_point_cloud_->attribute(sub_obj_att_id);
if (sub_obj_att_ == nullptr || sub_obj_att_->size() == 0)
return false;
return true;
}
bool ObjEncoder::EncodeMaterialFileName() {
const GeometryMetadata *pc_metadata = in_point_cloud_->GetMetadata();
if (!pc_metadata)
return true;
const AttributeMetadata *material_metadata =
pc_metadata->GetAttributeMetadataByStringEntry("name", "material");
if (!material_metadata)
return true;
std::string material_file_name;
if (!material_metadata->GetEntryString("file_name", &material_file_name))
return false;
buffer()->Encode("mtllib ", 7);
buffer()->Encode(material_file_name.c_str(), material_file_name.size());
buffer()->Encode("\n", 1);
material_id_to_name_.clear();
for (const auto &entry : material_metadata->entries()) {
// Material id must be int.
int value = 0;
// Found entry that are not material id, e.g. file name as a string.
if (!entry.second.GetValue(&value))
continue;
material_id_to_name_[value] = entry.first;
}
const int material_att_id = material_metadata->attribute_id();
material_att_ = in_point_cloud_->attribute(material_att_id);
if (material_att_ == nullptr || material_att_->size() == 0)
return false;
return true;
}
bool ObjEncoder::EncodePositions() {
const PointAttribute *const att =
in_point_cloud_->GetNamedAttribute(GeometryAttribute::POSITION);
@ -137,6 +208,12 @@ bool ObjEncoder::EncodeNormals() {
bool ObjEncoder::EncodeFaces() {
for (FaceIndex i(0); i < in_mesh_->num_faces(); ++i) {
if (sub_obj_att_)
if (!EncodeSubObject(i))
return false;
if (material_att_)
if (!EncodeMaterial(i))
return false;
buffer()->Encode('f');
for (int j = 0; j < 3; ++j) {
if (!EncodeFaceCorner(i, j))
@ -147,6 +224,49 @@ bool ObjEncoder::EncodeFaces() {
return true;
}
bool ObjEncoder::EncodeMaterial(FaceIndex face_id) {
int material_id = 0;
// Pick the first corner, all corners of a face should have same id.
const PointIndex vert_index = in_mesh_->face(face_id)[0];
const AttributeValueIndex index_id(material_att_->mapped_index(vert_index));
if (!material_att_->ConvertValue<int>(index_id, &material_id)) {
return false;
}
if (material_id != current_material_id_) {
// Update material information.
buffer()->Encode("usemtl ", 7);
const auto mat_ptr = material_id_to_name_.find(material_id);
// If the material id is not found.
if (mat_ptr == material_id_to_name_.end())
return false;
buffer()->Encode(mat_ptr->second.c_str(), mat_ptr->second.size());
buffer()->Encode("\n", 1);
current_material_id_ = material_id;
}
return true;
}
bool ObjEncoder::EncodeSubObject(FaceIndex face_id) {
int sub_obj_id = 0;
// Pick the first corner, all corners of a face should have same id.
const PointIndex vert_index = in_mesh_->face(face_id)[0];
const AttributeValueIndex index_id(sub_obj_att_->mapped_index(vert_index));
if (!sub_obj_att_->ConvertValue<int>(index_id, &sub_obj_id)) {
return false;
}
if (sub_obj_id != current_sub_obj_id_) {
buffer()->Encode("o ", 2);
const auto sub_obj_ptr = sub_obj_id_to_name_.find(sub_obj_id);
if (sub_obj_ptr == sub_obj_id_to_name_.end())
return false;
buffer()->Encode(sub_obj_ptr->second.c_str(), sub_obj_ptr->second.size());
buffer()->Encode("\n", 1);
current_sub_obj_id_ = sub_obj_id;
}
return true;
}
bool ObjEncoder::EncodeFaceCorner(FaceIndex face_id, int local_corner_id) {
buffer()->Encode(' ');
const PointIndex vert_index = in_mesh_->face(face_id)[local_corner_id];

View File

@ -42,10 +42,14 @@ class ObjEncoder {
bool ExitAndCleanup(bool return_value);
private:
bool GetSubObjects();
bool EncodeMaterialFileName();
bool EncodePositions();
bool EncodeTextureCoordinates();
bool EncodeNormals();
bool EncodeFaces();
bool EncodeSubObject(FaceIndex face_id);
bool EncodeMaterial(FaceIndex face_id);
bool EncodeFaceCorner(FaceIndex face_id, int local_corner_id);
void EncodeFloat(float val);
@ -57,6 +61,8 @@ class ObjEncoder {
const PointAttribute *pos_att_;
const PointAttribute *tex_coord_att_;
const PointAttribute *normal_att_;
const PointAttribute *material_att_;
const PointAttribute *sub_obj_att_;
// Buffer used for encoding float/int numbers.
char num_buffer_[20];
@ -65,6 +71,16 @@ class ObjEncoder {
const PointCloud *in_point_cloud_;
const Mesh *in_mesh_;
// Store sub object name for each value.
std::unordered_map<int, std::string> sub_obj_id_to_name_;
// Current sub object id of faces.
int current_sub_obj_id_;
// Store material name for each value in material attribute.
std::unordered_map<int, std::string> material_id_to_name_;
// Current material id of faces.
int current_material_id_;
};
} // namespace draco

View File

@ -0,0 +1,113 @@
// Copyright 2017 The Draco Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <sstream>
#include "draco/core/draco_test_base.h"
#include "draco/core/draco_test_utils.h"
#include "draco/io/obj_decoder.h"
#include "draco/io/obj_encoder.h"
namespace draco {
class ObjEncoderTest : public ::testing::Test {
protected:
template <class Geometry>
std::unique_ptr<Mesh> DecodeFromObjFile(const std::string &file_name) const {
const std::string path = GetTestFileFullPath(file_name);
std::unique_ptr<Mesh> mesh(new Mesh());
ObjDecoder decoder;
decoder.set_use_metadata(true);
if (!decoder.DecodeFromFile(path, mesh.get()))
return nullptr;
return mesh;
}
void CompareMeshes(const Mesh *mesh0, const Mesh *mesh1) {
ASSERT_EQ(mesh0->num_faces(), mesh1->num_faces());
ASSERT_EQ(mesh0->num_attributes(), mesh1->num_attributes());
for (size_t att_id = 0; att_id < mesh0->num_attributes(); ++att_id) {
ASSERT_EQ(mesh0->attribute(att_id)->size(),
mesh1->attribute(att_id)->size());
}
}
// Encode a mesh using the ObjEncoder and then decode to verify the encoding.
std::unique_ptr<Mesh> EncodeAndDecodeMesh(const Mesh *mesh) {
EncoderBuffer encoder_buffer;
ObjEncoder encoder;
if (!encoder.EncodeToBuffer(*mesh, &encoder_buffer))
return nullptr;
DecoderBuffer decoder_buffer;
decoder_buffer.Init(encoder_buffer.data(), encoder_buffer.size());
std::unique_ptr<Mesh> decoded_mesh(new Mesh());
ObjDecoder decoder;
decoder.set_use_metadata(true);
if (!decoder.DecodeFromBuffer(&decoder_buffer, decoded_mesh.get()))
return nullptr;
return decoded_mesh;
}
void test_encoding(const std::string &file_name) {
const std::unique_ptr<Mesh> mesh(DecodeFromObjFile<Mesh>(file_name));
ASSERT_NE(mesh, nullptr) << "Failed to load test model " << file_name;
ASSERT_GT(mesh->num_faces(), 0);
const std::unique_ptr<Mesh> decoded_mesh = EncodeAndDecodeMesh(mesh.get());
CompareMeshes(mesh.get(), decoded_mesh.get());
}
};
TEST_F(ObjEncoderTest, HasSubObject) { test_encoding("cube_att_sub_o.obj"); }
TEST_F(ObjEncoderTest, HasMaterial) {
const std::unique_ptr<Mesh> mesh0(DecodeFromObjFile<Mesh>("mat_test.obj"));
ASSERT_NE(mesh0, nullptr);
const std::unique_ptr<Mesh> mesh1 = EncodeAndDecodeMesh(mesh0.get());
ASSERT_NE(mesh1, nullptr);
ASSERT_EQ(mesh0->num_faces(), mesh1->num_faces());
ASSERT_EQ(mesh0->num_attributes(), mesh1->num_attributes());
// Position attribute should be the same.
ASSERT_EQ(mesh0->attribute(0)->size(), mesh1->attribute(0)->size());
// Since |mesh1| is decoded from buffer, it has not material file. So the
// size of material attribute is the number of materials used in the obj
// file which is 6. The size of material attribute of |mesh0| decoded from
// the obj file will be the number of materials defined in the .mtl file.
ASSERT_EQ(mesh0->attribute(1)->size(), 29);
ASSERT_EQ(mesh1->attribute(1)->size(), 6);
}
TEST_F(ObjEncoderTest, TestObjEncodingAll) {
// Test decoded mesh from encoded obj file stays the same.
test_encoding("bunny_norm.obj");
test_encoding("cube_att.obj");
test_encoding("cube_att_partial.obj");
test_encoding("cube_quads.obj");
test_encoding("cube_subd.obj");
test_encoding("extra_vertex.obj");
test_encoding("one_face_123.obj");
test_encoding("one_face_312.obj");
test_encoding("one_face_321.obj");
test_encoding("sphere.obj");
test_encoding("test_nm.obj");
test_encoding("test_nm_trans.obj");
test_encoding("test_sphere.obj");
test_encoding("three_faces_123.obj");
test_encoding("three_faces_312.obj");
test_encoding("two_faces_123.obj");
test_encoding("two_faces_312.obj");
}
} // namespace draco

View File

@ -129,6 +129,11 @@ const PointAttribute *Decoder::GetAttribute(const PointCloud &pc, long att_id) {
return pc.attribute(att_id);
}
const PointAttribute *Decoder::GetAttributeByUniqueId(const PointCloud &pc,
long unique_id) {
return pc.GetAttributeByUniqueId(unique_id);
}
long Decoder::GetAttributeIdByName(const PointCloud &pc,
const char *attribute_name) {
const std::string entry_value(attribute_name);

View File

@ -120,6 +120,10 @@ class Decoder {
const char *metadata_name,
const char *metadata_value);
// Returns an attribute id of an attribute that has the unqiue id.
static const draco::PointAttribute *GetAttributeByUniqueId(
const draco::PointCloud &pc, long unique_id);
// Returns a PointAttribute pointer from |att_id| index.
static const draco::PointAttribute *GetAttribute(const draco::PointCloud &pc,
long att_id);

View File

@ -158,6 +158,8 @@ interface Decoder {
[Const] DOMString value);
[Const] PointAttribute GetAttribute([Ref, Const] PointCloud pc, long att_id);
[Const] PointAttribute GetAttributeByUniqueId([Ref, Const] PointCloud pc,
long unique_id);
[Const] Metadata GetMetadata([Ref, Const] PointCloud pc);
[Const] Metadata GetAttributeMetadata([Ref, Const] PointCloud pc,

View File

@ -19,7 +19,7 @@ function isVersionSupported(versionString) {
const version = versionString.split('.');
if (version.length < 2 || version.length > 3)
return false; // Unexpected version string.
if (version[0] == 1 && version[1] == 0)
if (version[0] == 1 && version[1] >= 0 && version[1] <= 1)
return true;
if (version[0] != 0 || version[1] > 10)
return false;

View File

@ -13,6 +13,9 @@
// limitations under the License.
//
#include "draco/mesh/corner_table.h"
#include <limits>
#include "draco/mesh/corner_table_iterators.h"
namespace draco {
@ -49,6 +52,8 @@ bool CornerTable::Initialize(
bool CornerTable::Reset(int num_faces) {
if (num_faces < 0)
return false;
if (num_faces > std::numeric_limits<CornerIndex::ValueType>::max() / 3)
return false;
corner_to_vertex_map_.assign(num_faces * 3, kInvalidVertexIndex);
opposite_corners_.assign(num_faces * 3, kInvalidCornerIndex);
vertex_corners_.reserve(num_faces * 3);

View File

@ -37,6 +37,23 @@ std::unique_ptr<CornerTable> CreateCornerTable(const Mesh *mesh) {
return CT::Create(faces);
}
std::unique_ptr<CornerTable> CreateCornerTableFromAllAttributes(
const Mesh *mesh) {
IndexTypeVector<FaceIndex, FaceType> faces(mesh->num_faces());
FaceType new_face;
for (FaceIndex i(0); i < mesh->num_faces(); ++i) {
const Mesh::Face &face = mesh->face(i);
// Each face is identified by point indices that automatically split the
// mesh along attribute seams.
for (int j = 0; j < 3; ++j) {
new_face[j] = face[j].value();
}
faces[i] = new_face;
}
// Build the corner table.
return CornerTable::Create(faces);
}
PointIndex CornerToPointId(CornerIndex ci, const CornerTable *ct,
const Mesh *mesh) {
if (!ct->IsValid(ci))

View File

@ -23,9 +23,15 @@
namespace draco {
// Creates a CornerTable from |*mesh|. Returns nullptr on error.
// Creates a CornerTable from the position attribute of |mesh|. Returns nullptr
// on error.
std::unique_ptr<CornerTable> CreateCornerTable(const Mesh *mesh);
// Creates a CornerTable from all attributes of |mesh|. Boundaries are
// automatically introduced on all attribute seams. Returns nullptr on error.
std::unique_ptr<CornerTable> CreateCornerTableFromAllAttributes(
const Mesh *mesh);
// Returns the point id stored on corner |ci|.
PointIndex CornerToPointId(CornerIndex ci, const CornerTable *ct,
const Mesh *mesh);

View File

@ -63,6 +63,14 @@ const PointAttribute *PointCloud::GetNamedAttributeByUniqueId(
return nullptr;
}
const PointAttribute *PointCloud::GetAttributeByUniqueId(uint32_t id) const {
for (size_t att_id = 0; att_id < attributes_.size(); ++att_id) {
if (attributes_[att_id]->unique_id() == id)
return attributes_[att_id].get();
}
return nullptr;
}
int PointCloud::AddAttribute(std::unique_ptr<PointAttribute> pa) {
SetAttribute(attributes_.size(), std::move(pa));
return attributes_.size() - 1;

View File

@ -50,6 +50,9 @@ class PointCloud {
const PointAttribute *GetNamedAttributeByUniqueId(
GeometryAttribute::Type type, uint32_t id) const;
// Returns the attribute of a given unique id.
const PointAttribute *GetAttributeByUniqueId(uint32_t id) const;
int32_t num_attributes() const { return attributes_.size(); }
const PointAttribute *attribute(int32_t att_id) const {
DCHECK_LE(0, att_id);

View File

@ -32,6 +32,8 @@ struct Options {
bool tex_coords_deleted;
int normals_quantization_bits;
bool normals_deleted;
int generic_quantization_bits;
bool generic_deleted;
int compression_level;
bool use_metadata;
std::string input;
@ -45,6 +47,8 @@ Options::Options()
tex_coords_deleted(false),
normals_quantization_bits(10),
normals_deleted(false),
generic_quantization_bits(8),
generic_deleted(false),
compression_level(7) {}
void Usage() {
@ -66,11 +70,15 @@ void Usage() {
printf(
" -qn <value> quantization bits for the normal vector "
"attribute, default=10.\n");
printf(
" -qg <value> quantization bits for any generic attribute, "
"default=8.\n");
printf(
" -cl <value> compression level [0-10], most=10, least=0, "
"default=7.\n");
printf(
" --skip ATTRIBUTE_NAME skip a given attribute (NORMAL, TEX_COORD)\n");
" --skip ATTRIBUTE_NAME skip a given attribute (NORMAL, TEX_COORD, "
"GENERIC)\n");
printf(
"\nUse negative quantization values to skip the specified attribute\n");
printf(
@ -114,6 +122,17 @@ void PrintOptions(const draco::PointCloud &pc, const Options &options) {
} else if (options.normals_deleted) {
printf(" Normals: Skipped\n");
}
if (pc.GetNamedAttributeId(draco::GeometryAttribute::GENERIC) >= 0) {
if (options.generic_quantization_bits == 0) {
printf(" Generic: No quantization\n");
} else {
printf(" Generic: Quantization = %d bits\n",
options.generic_quantization_bits);
}
} else if (options.generic_deleted) {
printf(" Generic: Skipped\n");
}
printf("\n");
}
@ -209,6 +228,14 @@ int main(int argc, char **argv) {
"attribute is 31.\n");
return -1;
}
} else if (!strcmp("-qg", argv[i]) && i < argc_check) {
options.generic_quantization_bits = StringToInt(argv[++i]);
if (options.generic_quantization_bits > 31) {
printf(
"Error: The maximum number of quantization bits for generic "
"attributes is 31.\n");
return -1;
}
} else if (!strcmp("-cl", argv[i]) && i < argc_check) {
options.compression_level = StringToInt(argv[++i]);
} else if (!strcmp("--skip", argv[i]) && i < argc_check) {
@ -216,11 +243,14 @@ int main(int argc, char **argv) {
options.normals_quantization_bits = -1;
} else if (!strcmp("TEX_COORD", argv[i + 1])) {
options.tex_coords_quantization_bits = -1;
} else if (!strcmp("GENERIC", argv[i + 1])) {
options.generic_quantization_bits = -1;
} else {
printf("Error: Invalid attribute name after --skip\n");
return -1;
}
} else if (!strcmp("--metadata", argv[i]) && i < argc_check) {
++i;
} else if (!strcmp("--metadata", argv[i])) {
options.use_metadata = true;
}
}
@ -273,10 +303,19 @@ int main(int argc, char **argv) {
pc->GetNamedAttributeId(draco::GeometryAttribute::NORMAL, 0));
}
}
if (options.generic_quantization_bits < 0) {
if (pc->NumNamedAttributes(draco::GeometryAttribute::GENERIC) > 0) {
options.generic_deleted = true;
}
while (pc->NumNamedAttributes(draco::GeometryAttribute::GENERIC) > 0) {
pc->DeleteAttribute(
pc->GetNamedAttributeId(draco::GeometryAttribute::GENERIC, 0));
}
}
// If any attribute has been deleted, run deduplication of point indices again
// as some points can be possibly combined.
if (options.tex_coords_deleted || options.normals_deleted) {
if (options.tex_coords_deleted || options.normals_deleted ||
options.generic_deleted) {
pc->DeduplicatePointIds();
}
@ -297,6 +336,10 @@ int main(int argc, char **argv) {
encoder.SetAttributeQuantization(draco::GeometryAttribute::NORMAL,
options.normals_quantization_bits);
}
if (options.generic_quantization_bits > 0) {
encoder.SetAttributeQuantization(draco::GeometryAttribute::GENERIC,
options.generic_quantization_bits);
}
encoder.SetSpeedOptions(speed, speed);
if (options.output.empty()) {

View File

@ -4878,6 +4878,7 @@ f 2125 2124 2126
f 2128 2127 2130
f 2129 2128 2130
f 2132 2131 2136
usemtl unknown_mat_in_mtl_file
f 2133 2132 2136
f 2134 2133 2136
f 2135 2134 2136

Binary file not shown.

Binary file not shown.