Update Draco to 1.2.1

* Javascript and WebAssembly decoder size reduced by 35%
* Added specialized Javascript and Webassembly decoders for GLTF (size
reduction about 50% compared to the previous version)
This commit is contained in:
Ondrej Stava 2017-11-13 14:31:24 -08:00
parent 8492a2b279
commit a7c0d80a71
101 changed files with 854 additions and 292 deletions

View File

@ -29,23 +29,36 @@ option(ENABLE_MESH_COMPRESSION "" ON)
option(ENABLE_POINT_CLOUD_COMPRESSION "" ON)
option(ENABLE_PREDICTIVE_EDGEBREAKER "" ON)
option(ENABLE_STANDARD_EDGEBREAKER "" ON)
option(ENABLE_BACKWARDS_COMPATIBILITY "" ON)
option(ENABLE_DECODER_ATTRIBUTE_DEDUPLICATION "" OFF)
option(ENABLE_TESTS "Enables tests." OFF)
option(ENABLE_WASM "" OFF)
option(ENABLE_WERROR "" OFF)
option(ENABLE_WEXTRA "" OFF)
option(IGNORE_EMPTY_BUILD_TYPE "" OFF)
option(BUILD_FOR_GLTF "" OFF)
if (ENABLE_POINT_CLOUD_COMPRESSION)
add_cxx_preproc_definition("DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED")
endif ()
if (ENABLE_MESH_COMPRESSION)
add_cxx_preproc_definition("DRACO_MESH_COMPRESSION_SUPPORTED")
if (ENABLE_STANDARD_EDGEBREAKER)
add_cxx_preproc_definition("DRACO_STANDARD_EDGEBREAKER_SUPPORTED")
if (BUILD_FOR_GLTF)
# Override settings when building for GLTF.
add_cxx_preproc_definition("DRACO_MESH_COMPRESSION_SUPPORTED")
add_cxx_preproc_definition("DRACO_STANDARD_EDGEBREAKER_SUPPORTED")
else ()
if (ENABLE_POINT_CLOUD_COMPRESSION)
add_cxx_preproc_definition("DRACO_POINT_CLOUD_COMPRESSION_SUPPORTED")
endif ()
if (ENABLE_PREDICTIVE_EDGEBREAKER)
add_cxx_preproc_definition("DRACO_PREDICTIVE_EDGEBREAKER_SUPPORTED")
if (ENABLE_MESH_COMPRESSION)
add_cxx_preproc_definition("DRACO_MESH_COMPRESSION_SUPPORTED")
if (ENABLE_STANDARD_EDGEBREAKER)
add_cxx_preproc_definition("DRACO_STANDARD_EDGEBREAKER_SUPPORTED")
endif ()
if (ENABLE_PREDICTIVE_EDGEBREAKER)
add_cxx_preproc_definition("DRACO_PREDICTIVE_EDGEBREAKER_SUPPORTED")
endif ()
endif ()
if (ENABLE_BACKWARDS_COMPATIBILITY)
add_cxx_preproc_definition("DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED")
endif ()
endif ()
@ -669,6 +682,13 @@ if (EMSCRIPTEN)
append_link_flag_to_target(draco_encoder
"-s EXPORT_NAME=\"'DracoEncoderModule'\"")
target_compile_definitions(draco_encoder PRIVATE
DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED)
if (ENABLE_DECODER_ATTRIBUTE_DEDUPLICATION)
target_compile_definitions(draco_decoder PRIVATE
DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED)
endif ()
# Make $draco_js_sources source files depend on glue_decoder.cpp.
set_property(SOURCE ${draco_js_sources} APPEND PROPERTY OBJECT_DEPENDS
${draco_build_dir}/glue_decoder.cpp)
@ -794,6 +814,11 @@ else ()
draco_dec_config
draco_enc_config)
# For now, enable deduplication for both encoder and decoder.
# TODO(ostava): Support for disabling attribute deduplication for the C++
# decoder is planned in future releases.
add_preproc_definition(DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED)
if (BUILD_SHARED_LIBS)
set_target_properties(dracodec PROPERTIES SOVERSION 1)
set_target_properties(dracoenc PROPERTIES SOVERSION 1)

View File

@ -35,6 +35,8 @@ else ifeq ($(DRACO_CONFIG), full_point_cloud)
else
DRACO_CONFIG_DEFINES := $(DRACO_FULL_CONFIG_DEFINES)
endif
DRACO_CONFIG_DEFINES += -DDRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
#########
DEFINES := $(DRACO_CONFIG_DEFINES)

View File

@ -5,13 +5,10 @@
News
=======
### Version 1.2.0 release
The latest version of Draco brings a number of new compression enhancements and readies Draco for glTF 2.0 assets
* Improved compression:
* 5% improved compression for small assets
* Enhancements for upcoming Draco glTF2.0 extension
* Fixed Android build issues
* New, easier to use DRACOLoader.js
### Version 1.2.1 release
The latest version of Draco brings a number of enhancements to reduce decoder size and various other fixes
* Javascript and WebAssembly decoder size reduced by 35%
* Added specialized Javascript and Webassembly decoders for GLTF (size reduction about 50% compared to the previous version)
Description
===========

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

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -53,9 +53,9 @@ parent:d},u=null;d.asmPreload=d.asm;var q=d.reallocBuffer,r=function(a){a=Ea(a,d
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);Qa=n.GLOBAL_BASE;X=Qa+28912;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=28912;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||
return q};var x=d.asm})(a);Qa=n.GLOBAL_BASE;X=Qa+23504;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=23504;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,
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=492;a.wasmMaxTableSize=492;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"!==

View File

@ -0,0 +1,124 @@
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,r){if(h){f=$jscomp.global;e=e.split(".");for(r=0;r<e.length-1;r++){var k=e[r];k in f||(f[k]={});f=f[k]}e=e[e.length-1];r=f[e];h=h(r);h!=r&&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.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 r=$jscomp.global.setTimeout;h.prototype.asyncExecuteFunction=function(e){r(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,
r=new k(function(e,f){t=e;ia=f});this.callWhenSettled_(h(e,t),h(f,ia));return r};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),r=t.next();!r.done;r=t.next())f(r.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 r(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_(r(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 r(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 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){A.varargs=b;try{var c=A.get(),g=A.get(),e=A.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 z=c[d++]&63;if(248==(e&252))e=
(e&3)<<24|h<<18|k<<12|l<<6|z;else{var m=c[d++]&63;e=(e&1)<<30|h<<24|k<<18|l<<12|z<<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]&&2>=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=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=r(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 z=k[m],n=e[m];"number"!==n&&(n=f[n+"ToC"],c+="var "+n.arguments+" = "+z+";",c+=n.body+";",c+=z+"=("+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 $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(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=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"===A?q(a):r(a)};var A="";d.asm=function(a,g,h){if(!g.table){var z=d.wasmTableSize;void 0===z&&(z=1024);var p=d.wasmMaxTableSize;g.table="object"===
typeof WebAssembly&&"function"===typeof WebAssembly.Table?void 0!==p?new WebAssembly.Table({initial:z,maximum:p,element:"anyfunc"}):new WebAssembly.Table({initial:z,element:"anyfunc"}):Array(z);d.wasmTable=g.table}g.memoryBase||(g.memoryBase=d.STATIC_BASE);g.tableBase||(g.tableBase=0);var q;z=m.split(",");for(p=0;p<z.length;p++){var w=z[p];A=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);Qa=n.GLOBAL_BASE;X=Qa+17792;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=17792;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 A={varargs:0,get:function(a){A.varargs+=4;return u[A.varargs-4>>2]},getStr:function(){return t(A.get())},get64:function(){var a=A.get(),b=A.get();0<=a?f(0===b):f(-1===b);return a},getZero:function(){f(0===A.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=468;a.wasmMaxTableSize=468;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(z){if("number"!==typeof z&&"longjmp"!==z)throw z;
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(z){if("number"!==typeof z&&"longjmp"!==z)throw z;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(Fa){if("number"!==typeof Fa&&"longjmp"!==Fa)throw Fa;a.setThrew(1,0)}},_pthread_getspecific:function(a){return Ca[a]||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.";},_pthread_key_create:function(a,b){if(0==a)return 22;u[a>>2]=Ta;Ca[Ta]=0;Ta++;return 0},_abort:function(){a.abort()},___setErrNo:function(d){a.___errno_location&&(u[a.___errno_location()>>2]=d);return d},
___syscall6:function(a,b){A.varargs=b;try{var c=A.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},___gxx_personality_v0:function(){},___syscall140:function(a,
b){A.varargs=b;try{var c=A.getStreamFromFD();A.get();var d=A.get(),e=A.get(),f=A.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

@ -5,13 +5,10 @@
News
=======
### Version 1.2.0 release
The latest version of Draco brings a number of new compression enhancements and readies Draco for glTF 2.0 assets
* Improved compression:
* 5% improved compression for small assets
* Enhancements for upcoming Draco glTF2.0 extension
* Fixed Android build issues
* New, easier to use DRACOLoader.js
### Version 1.2.1 release
The latest version of Draco brings a number of enhancements to reduce decoder size and various other fixes
* Javascript and WebAssembly decoder size reduced by 35%
* Added specialized Javascript and Webassembly decoders for GLTF (size reduction about 50% compared to the previous version)
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.1.0",
"version": "1.2.2",
"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

@ -118,48 +118,63 @@ class GeometryAttribute {
buffer_->Read(byte_pos, out_data, byte_stride_);
}
// DEPRECATED: Use
// ConvertValue(AttributeValueIndex att_id,
// int out_num_components,
// OutT *out_val);
//
// Function for conversion of a attribute to a specific output format.
// OutT is the desired data type of the attribute.
// out_att_components_t is the number of components of the output format.
// Returns false when the conversion failed.
template <typename OutT, int out_att_components_t>
bool ConvertValue(AttributeValueIndex att_id, OutT *out_val) const {
return ConvertValue(att_id, out_att_components_t, out_val);
}
// Function for conversion of a attribute to a specific output format.
// |out_val| needs to be able to store |out_num_components| values.
// OutT is the desired data type of the attribute.
// Returns false when the conversion failed.
template <typename OutT>
bool ConvertValue(AttributeValueIndex att_id, int8_t out_num_components,
OutT *out_val) const {
if (out_val == nullptr)
return false;
switch (data_type_) {
case DT_INT8:
return ConvertTypedValue<int8_t, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<int8_t, OutT>(att_id, out_num_components,
out_val);
case DT_UINT8:
return ConvertTypedValue<uint8_t, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<uint8_t, OutT>(att_id, out_num_components,
out_val);
case DT_INT16:
return ConvertTypedValue<int16_t, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<int16_t, OutT>(att_id, out_num_components,
out_val);
case DT_UINT16:
return ConvertTypedValue<uint16_t, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<uint16_t, OutT>(att_id, out_num_components,
out_val);
case DT_INT32:
return ConvertTypedValue<int32_t, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<int32_t, OutT>(att_id, out_num_components,
out_val);
case DT_UINT32:
return ConvertTypedValue<uint32_t, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<uint32_t, OutT>(att_id, out_num_components,
out_val);
case DT_INT64:
return ConvertTypedValue<int64_t, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<int64_t, OutT>(att_id, out_num_components,
out_val);
case DT_UINT64:
return ConvertTypedValue<uint64_t, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<uint64_t, OutT>(att_id, out_num_components,
out_val);
case DT_FLOAT32:
return ConvertTypedValue<float, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<float, OutT>(att_id, out_num_components,
out_val);
case DT_FLOAT64:
return ConvertTypedValue<double, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<double, OutT>(att_id, out_num_components,
out_val);
case DT_BOOL:
return ConvertTypedValue<bool, OutT, out_att_components_t>(att_id,
out_val);
return ConvertTypedValue<bool, OutT>(att_id, out_num_components,
out_val);
default:
// Wrong attribute type.
return false;
@ -173,19 +188,7 @@ class GeometryAttribute {
// Returns false when the conversion failed.
template <typename OutT>
bool ConvertValue(AttributeValueIndex att_index, OutT *out_value) const {
switch (num_components_) {
case 1:
return ConvertValue<OutT, 1>(att_index, out_value);
case 2:
return ConvertValue<OutT, 2>(att_index, out_value);
case 3:
return ConvertValue<OutT, 3>(att_index, out_value);
case 4:
return ConvertValue<OutT, 4>(att_index, out_value);
default:
break;
}
return false;
return ConvertValue<OutT>(att_index, num_components_, out_value);
}
bool operator==(const GeometryAttribute &va) const;
@ -223,18 +226,16 @@ class GeometryAttribute {
// Function for conversion of an attribute to a specific output format given a
// format of the stored attribute.
// T is the stored attribute data type.
// att_components_t is the number of the stored attribute components.
// OutT is the desired data type of the attribute.
// out_att_components_t is the number of components of the output format.
template <typename T, int att_components_t, typename OutT,
int out_att_components_t>
bool ConvertTypedValue(AttributeValueIndex att_id, OutT *out_value) const {
std::array<T, att_components_t> att_value;
if (!GetValue<T, att_components_t>(att_id, &att_value))
return false;
template <typename T, typename OutT>
bool ConvertTypedValue(AttributeValueIndex att_id, int8_t out_num_components,
OutT *out_value) const {
const uint8_t *src_address = GetAddress(att_id);
// Convert all components available in both the original and output formats.
for (int i = 0; i < std::min(att_components_t, out_att_components_t); ++i) {
out_value[i] = static_cast<OutT>(att_value[i]);
for (int i = 0; i < std::min(num_components_, out_num_components); ++i) {
const T in_value = *reinterpret_cast<const T *>(src_address);
out_value[i] = static_cast<OutT>(in_value);
// When converting integer to floating point, normalize the value if
// necessary.
if (std::is_integral<T>::value && std::is_floating_point<OutT>::value &&
@ -246,39 +247,15 @@ class GeometryAttribute {
// normalized, integer values should be converted as if they represent 0-1
// range. E.g. when we convert uint16 to uint8, the range <0, 2^16 - 1>
// should be converted to range <0, 2^8 - 1>.
src_address += sizeof(T);
}
// Fill empty data for unused output components if needed.
for (int i = att_components_t; i < out_att_components_t; ++i) {
for (int i = num_components_; i < out_num_components; ++i) {
out_value[i] = static_cast<OutT>(0);
}
return true;
}
// The same as above but without a component specifier for input attribute.
template <typename T, typename OutT, int OUT_CMPS>
bool ConvertTypedValue(AttributeValueIndex att_index, OutT *out_value) const {
bool rv = false;
// Select the right method to call based on the number of attribute
// components.
switch (num_components_) {
case 1:
rv = ConvertTypedValue<T, 1, OutT, OUT_CMPS>(att_index, out_value);
break;
case 2:
rv = ConvertTypedValue<T, 2, OutT, OUT_CMPS>(att_index, out_value);
break;
case 3:
rv = ConvertTypedValue<T, 3, OutT, OUT_CMPS>(att_index, out_value);
break;
case 4:
rv = ConvertTypedValue<T, 4, OutT, OUT_CMPS>(att_index, out_value);
break;
default:
return false; // This shouldn't happen.
}
return rv;
}
DataBuffer *buffer_;
// The buffer descriptor is stored at the time the buffer is attached to this
// attribute. The purpose is to detect if any changes happened to the buffer

View File

@ -64,6 +64,7 @@ bool PointAttribute::Reset(size_t num_attribute_values) {
return true;
}
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
AttributeValueIndex::ValueType PointAttribute::DeduplicateValues(
const GeometryAttribute &in_att) {
return DeduplicateValues(in_att, AttributeValueIndex(0));
@ -199,5 +200,6 @@ AttributeValueIndex::ValueType PointAttribute::DeduplicateFormattedValues(
num_unique_entries_ = unique_vals.value();
return num_unique_entries_;
}
#endif
} // namespace draco

View File

@ -103,6 +103,7 @@ class PointAttribute : public GeometryAttribute {
return GetValue(mapped_index(point_index), out_data);
}
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
// Deduplicate |in_att| values into |this| attribute. |in_att| can be equal
// to |this|.
// Returns -1 if the deduplication failed.
@ -113,6 +114,7 @@ class PointAttribute : public GeometryAttribute {
// provided offset |in_att_offset|.
AttributeValueIndex::ValueType DeduplicateValues(
const GeometryAttribute &in_att, AttributeValueIndex in_att_offset);
#endif
// Set attribute transform data for the attribute. The data is used to store
// the type and parameters of the transform that is applied on the attribute
@ -126,12 +128,14 @@ class PointAttribute : public GeometryAttribute {
}
private:
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
template <typename T>
AttributeValueIndex::ValueType DeduplicateTypedValues(
const GeometryAttribute &in_att, AttributeValueIndex in_att_offset);
template <typename T, int COMPONENTS_COUNT>
AttributeValueIndex::ValueType DeduplicateFormattedValues(
const GeometryAttribute &in_att, AttributeValueIndex in_att_offset);
#endif
// Data storage for attribute values. GeometryAttribute itself doesn't own its
// buffer so we need to allocate it here.

View File

@ -30,11 +30,14 @@ bool AttributesDecoder::Initialize(PointCloudDecoder *decoder, PointCloud *pc) {
bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
// Decode and create attributes.
uint32_t num_attributes;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (point_cloud_decoder_->bitstream_version() <
DRACO_BITSTREAM_VERSION(2, 0)) {
if (!in_buffer->Decode(&num_attributes))
return false;
} else {
} else
#endif
{
if (!DecodeVarint(&num_attributes, in_buffer))
return false;
}
@ -63,17 +66,20 @@ bool AttributesDecoder::DecodeAttributesDecoderData(DecoderBuffer *in_buffer) {
num_components, draco_dt, normalized > 0,
DataTypeLength(draco_dt) * num_components, 0);
uint32_t unique_id;
if (point_cloud_decoder_->bitstream_version() >=
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (point_cloud_decoder_->bitstream_version() <
DRACO_BITSTREAM_VERSION(1, 3)) {
DecodeVarint(&unique_id, in_buffer);
ga.set_unique_id(unique_id);
} else {
uint16_t custom_id;
if (!in_buffer->Decode(&custom_id))
return false;
// TODO(zhafang): Add "custom_id" to attribute metadata.
unique_id = static_cast<uint32_t>(custom_id);
ga.set_unique_id(unique_id);
} else
#endif
{
DecodeVarint(&unique_id, in_buffer);
ga.set_unique_id(unique_id);
}
const int att_id = pc->AddAttribute(
std::unique_ptr<PointAttribute>(new PointAttribute(ga)));

View File

@ -32,6 +32,8 @@ class LinearSequencer : public PointsSequencer {
protected:
bool GenerateSequenceInternal() override {
if (num_points_ < 0)
return false;
out_point_ids()->resize(num_points_);
for (int i = 0; i < num_points_; ++i) {
out_point_ids()->at(i) = PointIndex(i);

View File

@ -54,7 +54,7 @@ class OctahedronToolBox {
max_value_(-1),
center_value_(-1) {}
OctahedronToolBox(int32_t q) { this->SetQuantizationBits(q); }
explicit OctahedronToolBox(int32_t q) { this->SetQuantizationBits(q); }
void SetQuantizationBits(int32_t q) {
DCHECK_GE(q, 2);

View File

@ -183,6 +183,7 @@ template <typename DataTypeT, class TransformT, class MeshDataT>
bool MeshPredictionSchemeConstrainedMultiParallelogramDecoder<
DataTypeT, TransformT, MeshDataT>::DecodePredictionData(DecoderBuffer
*buffer) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
// Decode prediction mode.
uint8_t mode;
@ -195,6 +196,7 @@ bool MeshPredictionSchemeConstrainedMultiParallelogramDecoder<
return false;
}
}
#endif
// Encode selected edges using separate rans bit coder for each context.
for (int i = 0; i < kMaxNumParallelograms; ++i) {

View File

@ -136,6 +136,7 @@ bool MeshPredictionSchemeGeometricNormalDecoder<
if (!this->transform().DecodeTransformData(buffer))
return false;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
uint8_t prediction_mode;
buffer->Decode(&prediction_mode);
@ -144,6 +145,7 @@ bool MeshPredictionSchemeGeometricNormalDecoder<
NormalPredictionMode(prediction_mode)))
return false;
}
#endif
// Init normal flips.
if (!flip_normal_bit_decoder_.StartDecoding(buffer))

View File

@ -30,7 +30,7 @@ class MeshPredictionSchemeGeometricNormalPredictorArea
Base;
public:
MeshPredictionSchemeGeometricNormalPredictorArea(const MeshDataT &md)
explicit MeshPredictionSchemeGeometricNormalPredictorArea(const MeshDataT &md)
: Base(md) {
this->SetNormalPredictionMode(TRIANGLE_AREA);
};

View File

@ -31,7 +31,7 @@ namespace draco {
template <typename DataTypeT, class TransformT, class MeshDataT>
class MeshPredictionSchemeGeometricNormalPredictorBase {
protected:
MeshPredictionSchemeGeometricNormalPredictorBase(const MeshDataT &md)
explicit MeshPredictionSchemeGeometricNormalPredictorBase(const MeshDataT &md)
: pos_attribute_(nullptr),
entry_to_point_id_map_(nullptr),
mesh_data_(md) {}

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_MULTI_PARALLELOGRAM_DECODER_H_
#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_MULTI_PARALLELOGRAM_DECODER_H_
@ -118,3 +119,4 @@ bool MeshPredictionSchemeMultiParallelogramDecoder<DataTypeT, TransformT,
} // namespace draco
#endif // DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_MULTI_PARALLELOGRAM_DECODER_H_
#endif

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_TEX_COORDS_DECODER_H_
#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_TEX_COORDS_DECODER_H_
@ -72,6 +73,8 @@ class MeshPredictionSchemeTexCoordsDecoder
}
bool SetParentAttribute(const PointAttribute *att) override {
if (att == nullptr)
return false;
if (att->attribute_type() != GeometryAttribute::POSITION)
return false; // Invalid attribute type.
if (att->num_components() != 3)
@ -322,3 +325,4 @@ void MeshPredictionSchemeTexCoordsDecoder<DataTypeT, TransformT, MeshDataT>::
} // namespace draco
#endif // DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_MESH_PREDICTION_SCHEME_TEX_COORDS_DECODER_H_
#endif

View File

@ -28,7 +28,7 @@ namespace draco {
template <typename DataTypeT, class MeshDataT>
class MeshPredictionSchemeTexCoordsPortablePredictor {
public:
MeshPredictionSchemeTexCoordsPortablePredictor(const MeshDataT &md)
explicit MeshPredictionSchemeTexCoordsPortablePredictor(const MeshDataT &md)
: pos_attribute_(nullptr),
entry_to_point_id_map_(nullptr),
mesh_data_(md) {}

View File

@ -31,10 +31,19 @@
namespace draco {
// Factory class for creating mesh prediction schemes.
// Factory class for creating mesh prediction schemes. The factory implements
// operator() that is used to create an appropriate mesh prediction scheme in
// CreateMeshPredictionScheme() function in prediction_scheme_factory.h
template <typename DataTypeT>
struct MeshPredictionSchemeDecoderFactory {
template <class TransformT, class MeshDataT>
// Operator () specialized for the wrap transform. Wrap transform can be used
// for all mesh prediction schemes. The specialization is done in compile time
// to prevent instantiations of unneeded combinations of prediction schemes +
// prediction transforms.
template <
class TransformT, class MeshDataT,
typename std::enable_if<
TransformT::GetType() == PREDICTION_TRANSFORM_WRAP, int>::type = 0>
std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>> operator()(
PredictionSchemeMethod method, const PointAttribute *attribute,
const TransformT &transform, const MeshDataT &mesh_data,
@ -44,22 +53,30 @@ struct MeshPredictionSchemeDecoderFactory {
new MeshPredictionSchemeParallelogramDecoder<DataTypeT, TransformT,
MeshDataT>(
attribute, transform, mesh_data));
} else if (method == MESH_PREDICTION_MULTI_PARALLELOGRAM) {
}
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
else if (method == MESH_PREDICTION_MULTI_PARALLELOGRAM) {
return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
new MeshPredictionSchemeMultiParallelogramDecoder<
DataTypeT, TransformT, MeshDataT>(attribute, transform,
mesh_data));
} else if (method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM) {
}
#endif
else if (method == MESH_PREDICTION_CONSTRAINED_MULTI_PARALLELOGRAM) {
return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
new MeshPredictionSchemeConstrainedMultiParallelogramDecoder<
DataTypeT, TransformT, MeshDataT>(attribute, transform,
mesh_data));
} else if (method == MESH_PREDICTION_TEX_COORDS) {
}
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
else if (method == MESH_PREDICTION_TEX_COORDS) {
return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
new MeshPredictionSchemeTexCoordsDecoder<DataTypeT, TransformT,
MeshDataT>(
attribute, transform, mesh_data, bitstream_version));
} else if (method == MESH_PREDICTION_TEX_COORDS_PORTABLE) {
}
#endif
else if (method == MESH_PREDICTION_TEX_COORDS_PORTABLE) {
return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
new MeshPredictionSchemeTexCoordsPortableDecoder<
DataTypeT, TransformT, MeshDataT>(attribute, transform,
@ -72,6 +89,30 @@ struct MeshPredictionSchemeDecoderFactory {
}
return nullptr;
}
// Operator () specialized for normal octahedron transforms. These transforms
// are currently used only by the geometric normal prediction scheme (the
// transform is also used by delta coding, but delta predictor is not
// constructed in this function).
template <
class TransformT, class MeshDataT,
typename std::enable_if<
TransformT::GetType() ==
PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED ||
TransformT::GetType() == PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON,
int>::type = 0>
std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>> operator()(
PredictionSchemeMethod method, const PointAttribute *attribute,
const TransformT &transform, const MeshDataT &mesh_data,
uint16_t bitstream_version) {
if (method == MESH_PREDICTION_GEOMETRIC_NORMAL) {
return std::unique_ptr<PredictionSchemeDecoder<DataTypeT, TransformT>>(
new MeshPredictionSchemeGeometricNormalDecoder<DataTypeT, TransformT,
MeshDataT>(
attribute, transform, mesh_data));
}
return nullptr;
}
};
// Creates a prediction scheme for a given decoder and given prediction method.

View File

@ -57,7 +57,7 @@ class PredictionSchemeNormalOctahedronCanonicalizedEncodingTransform
typedef DataTypeT DataType;
// We expect the mod value to be of the form 2^b-1.
PredictionSchemeNormalOctahedronCanonicalizedEncodingTransform(
explicit PredictionSchemeNormalOctahedronCanonicalizedEncodingTransform(
DataType max_quantized_value)
: Base(max_quantized_value) {}

View File

@ -39,10 +39,11 @@ class PredictionSchemeNormalOctahedronCanonicalizedTransformBase
PredictionSchemeNormalOctahedronCanonicalizedTransformBase() : Base() {}
// We expect the mod value to be of the form 2^b-1.
PredictionSchemeNormalOctahedronCanonicalizedTransformBase(DataType mod_value)
explicit PredictionSchemeNormalOctahedronCanonicalizedTransformBase(
DataType mod_value)
: Base(mod_value) {}
PredictionSchemeTransformType GetType() const override {
static constexpr PredictionSchemeTransformType GetType() {
return PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED;
}

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
#ifndef DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_NORMAL_OCTAHEDRON_DECODING_TRANSFORM_H_
#define DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_NORMAL_OCTAHEDRON_DECODING_TRANSFORM_H_
@ -97,3 +98,4 @@ class PredictionSchemeNormalOctahedronDecodingTransform
} // namespace draco
#endif // DRACO_COMPRESSION_ATTRIBUTES_PREDICTION_SCHEMES_PREDICTION_SCHEME_NORMAL_OCTAHEDRON_DECODING_TRANSFORM_H_
#endif

View File

@ -51,7 +51,7 @@ class PredictionSchemeNormalOctahedronEncodingTransform
typedef DataTypeT DataType;
// We expect the mod value to be of the form 2^b-1.
PredictionSchemeNormalOctahedronEncodingTransform(
explicit PredictionSchemeNormalOctahedronEncodingTransform(
DataType max_quantized_value)
: Base(max_quantized_value) {}

View File

@ -36,13 +36,12 @@ class PredictionSchemeNormalOctahedronTransformBase {
PredictionSchemeNormalOctahedronTransformBase() {}
// We expect the mod value to be of the form 2^b-1.
PredictionSchemeNormalOctahedronTransformBase(DataType max_quantized_value) {
explicit PredictionSchemeNormalOctahedronTransformBase(
DataType max_quantized_value) {
this->set_max_quantized_value(max_quantized_value);
}
virtual ~PredictionSchemeNormalOctahedronTransformBase() {}
virtual PredictionSchemeTransformType GetType() const {
static constexpr PredictionSchemeTransformType GetType() {
return PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON;
}

View File

@ -52,6 +52,8 @@ class PredictionSchemeWrapDecodingTransform
return false;
if (!buffer->Decode(&max_value))
return false;
if (min_value > max_value)
return false;
this->set_min_value(min_value);
this->set_max_value(max_value);
this->InitCorrectionBounds();

View File

@ -47,7 +47,7 @@ class PredictionSchemeWrapTransformBase {
max_correction_(0),
min_correction_(0) {}
PredictionSchemeTransformType GetType() const {
static constexpr PredictionSchemeTransformType GetType() {
return PREDICTION_TRANSFORM_WRAP;
}

View File

@ -75,11 +75,14 @@ bool SequentialAttributeDecoder::InitPredictionScheme(
ps->GetParentAttributeType(i));
if (att_id == -1)
return false; // Requested attribute does not exist.
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
if (!ps->SetParentAttribute(decoder_->point_cloud()->attribute(att_id))) {
return false;
}
} else {
} else
#endif
{
if (!ps->SetParentAttribute(decoder_->GetPortableAttribute(att_id))) {
return false;
}

View File

@ -29,7 +29,7 @@ namespace draco {
// encoded by the encoder.
class SequentialAttributeDecodersController : public AttributesDecoder {
public:
SequentialAttributeDecodersController(
explicit SequentialAttributeDecodersController(
std::unique_ptr<PointsSequencer> sequencer);
bool DecodeAttributesDecoderData(DecoderBuffer *buffer) override;

View File

@ -31,15 +31,16 @@ bool SequentialIntegerAttributeDecoder::Initialize(PointCloudDecoder *decoder,
bool SequentialIntegerAttributeDecoder::TransformAttributeToOriginalFormat(
const std::vector<PointIndex> &point_ids) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder() &&
decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0))
return true; // Don't revert the transform here for older files.
#endif
return StoreValues(point_ids.size());
}
bool SequentialIntegerAttributeDecoder::DecodeValues(
const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
const int32_t num_values = point_ids.size();
// Decode prediction scheme.
int8_t prediction_scheme_method;
in_buffer->Decode(&prediction_scheme_method);
@ -59,12 +60,15 @@ bool SequentialIntegerAttributeDecoder::DecodeValues(
if (!DecodeIntegerValues(point_ids, in_buffer))
return false;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
const int32_t num_values = point_ids.size();
if (decoder() &&
decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
// For older files, revert the transform right after we decode the data.
if (!StoreValues(num_values))
return false;
}
#endif
return true;
}
@ -84,8 +88,8 @@ bool SequentialIntegerAttributeDecoder::DecodeIntegerValues(
const int num_components = GetNumValueComponents();
if (num_components <= 0)
return false;
const int32_t num_entries = point_ids.size();
const int32_t num_values = num_entries * num_components;
const size_t num_entries = point_ids.size();
const size_t num_values = num_entries * num_components;
PreparePortableAttribute(num_entries, num_components);
int32_t *const portable_attribute_data = GetPortableAttributeData();
uint8_t compressed;
@ -114,7 +118,7 @@ bool SequentialIntegerAttributeDecoder::DecodeIntegerValues(
return false;
if (in_buffer->remaining_size() < num_bytes * num_values)
return false;
for (uint32_t i = 0; i < num_values; ++i) {
for (size_t i = 0; i < num_values; ++i) {
in_buffer->Decode(portable_attribute_data + i, num_bytes);
}
}

View File

@ -36,12 +36,14 @@ bool SequentialNormalAttributeDecoder::Initialize(PointCloudDecoder *decoder,
bool SequentialNormalAttributeDecoder::DecodeIntegerValues(
const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
uint8_t quantization_bits;
if (!in_buffer->Decode(&quantization_bits))
return false;
quantization_bits_ = quantization_bits;
}
#endif
return SequentialIntegerAttributeDecoder::DecodeIntegerValues(point_ids,
in_buffer);
}

View File

@ -48,6 +48,7 @@ class SequentialNormalAttributeDecoder
PredictionSchemeMethod method,
PredictionSchemeTransformType transform_type) override {
switch (transform_type) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
case PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON: {
typedef PredictionSchemeNormalOctahedronDecodingTransform<int32_t>
Transform;
@ -57,6 +58,7 @@ class SequentialNormalAttributeDecoder
return CreatePredictionSchemeForDecoder<int32_t, Transform>(
method, attribute_id(), decoder());
}
#endif
case PREDICTION_TRANSFORM_NORMAL_OCTAHEDRON_CANONICALIZED: {
typedef PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform<
int32_t>

View File

@ -36,9 +36,11 @@ bool SequentialQuantizationAttributeDecoder::Initialize(
bool SequentialQuantizationAttributeDecoder::DecodeIntegerValues(
const std::vector<PointIndex> &point_ids, DecoderBuffer *in_buffer) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder()->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0) &&
!DecodeQuantizedDataInfo())
return false;
#endif
return SequentialIntegerAttributeDecoder::DecodeIntegerValues(point_ids,
in_buffer);
}
@ -82,14 +84,16 @@ bool SequentialQuantizationAttributeDecoder::DecodeQuantizedDataInfo() {
bool SequentialQuantizationAttributeDecoder::DequantizeValues(
uint32_t num_values) {
// Convert all quantized values back to floats.
const int32_t max_quantized_value = (1 << (quantization_bits_)) - 1;
const int32_t max_quantized_value =
(1u << static_cast<uint32_t>(quantization_bits_)) - 1;
const int num_components = attribute()->num_components();
const int entry_size = sizeof(float) * num_components;
const std::unique_ptr<float[]> att_val(new float[num_components]);
int quant_val_id = 0;
int out_byte_pos = 0;
Dequantizer dequantizer;
dequantizer.Init(max_value_dif_, max_quantized_value);
if (!dequantizer.Init(max_value_dif_, max_quantized_value))
return false;
const int32_t *const portable_attribute_data = GetPortableAttributeData();
for (uint32_t i = 0; i < num_values; ++i) {
for (int c = 0; c < num_components; ++c) {

View File

@ -36,8 +36,25 @@ bool SequentialQuantizationAttributeEncoder::Initialize(
attribute_id, "quantization_bits", -1);
if (quantization_bits < 1)
return false;
attribute_quantization_transform_.ComputeParameters(*attribute,
quantization_bits);
if (encoder->options()->IsAttributeOptionSet(attribute_id,
"quantization_origin") &&
encoder->options()->IsAttributeOptionSet(attribute_id,
"quantization_range")) {
// Quantization settings are explicitly specified in the provided options.
std::vector<float> quantization_origin(attribute->num_components());
encoder->options()->GetAttributeVector(attribute_id, "quantization_origin",
attribute->num_components(),
&quantization_origin[0]);
const float range = encoder->options()->GetAttributeFloat(
attribute_id, "quantization_range", 1.f);
attribute_quantization_transform_.SetParameters(
quantization_bits, quantization_origin.data(),
attribute->num_components(), range);
} else {
// Compute quantization settings from the attribute values.
attribute_quantization_transform_.ComputeParameters(*attribute,
quantization_bits);
}
return true;
}

View File

@ -110,6 +110,14 @@ enum MeshTraversalMethod {
MESH_TRAVERSAL_RESERVED_2 = 3,
};
// List of all variant of the edgebreaker method that is used for compression
// of mesh connectivity.
enum MeshEdgeBreakerConnectivityEncodingMethod {
MESH_EDGEBREAKER_STANDARD_ENCODING = 0,
MESH_EDGEBREAKER_PREDICTIVE_ENCODING = 1, // Deprecated.
MESH_EDGEBREAKER_VALENCE_ENCODING = 2,
};
// Draco header V1
struct DracoHeader {
int8_t draco_string[5];

View File

@ -64,10 +64,21 @@ class DracoOptions {
void SetAttributeInt(const AttributeKey &att_key, const std::string &name,
int val);
float GetAttributeFloat(const AttributeKey &att_key, const std::string &name,
float default_val) const;
void SetAttributeFloat(const AttributeKey &att_key, const std::string &name,
float val);
bool GetAttributeBool(const AttributeKey &att_key, const std::string &name,
bool default_val) const;
void SetAttributeBool(const AttributeKey &att_key, const std::string &name,
bool val);
template <typename DataTypeT>
bool GetAttributeVector(const AttributeKey &att_key, const std::string &name,
int num_dims, DataTypeT *val) const;
template <typename DataTypeT>
void SetAttributeVector(const AttributeKey &att_key, const std::string &name,
int num_dims, const DataTypeT *val);
bool IsAttributeOptionSet(const AttributeKey &att_key,
const std::string &name) const;
@ -78,12 +89,28 @@ class DracoOptions {
void SetGlobalInt(const std::string &name, int val) {
global_options_.SetInt(name, val);
}
float GetGlobalFloat(const std::string &name, float default_val) const {
return global_options_.GetFloat(name, default_val);
}
void SetGlobalFloat(const std::string &name, float val) {
global_options_.SetFloat(name, val);
}
bool GetGlobalBool(const std::string &name, bool default_val) const {
return global_options_.GetBool(name, default_val);
}
void SetGlobalBool(const std::string &name, bool val) {
global_options_.SetBool(name, val);
}
template <typename DataTypeT>
bool GetGlobalVector(const std::string &name, int num_dims,
DataTypeT *val) const {
return global_options_.GetVector(name, num_dims, val);
}
template <typename DataTypeT>
void SetGlobalVector(const std::string &name, int num_dims,
const DataTypeT *val) {
global_options_.SetVector(name, val, num_dims);
}
bool IsGlobalOptionSet(const std::string &name) const {
return global_options_.IsOptionSet(name);
}
@ -144,6 +171,22 @@ void DracoOptions<AttributeKeyT>::SetAttributeInt(const AttributeKeyT &att_key,
GetAttributeOptions(att_key)->SetInt(name, val);
}
template <typename AttributeKeyT>
float DracoOptions<AttributeKeyT>::GetAttributeFloat(
const AttributeKeyT &att_key, const std::string &name,
float default_val) const {
const Options *const att_options = FindAttributeOptions(att_key);
if (att_options && att_options->IsOptionSet(name))
return att_options->GetFloat(name, default_val);
return global_options_.GetFloat(name, default_val);
}
template <typename AttributeKeyT>
void DracoOptions<AttributeKeyT>::SetAttributeFloat(
const AttributeKeyT &att_key, const std::string &name, float val) {
GetAttributeOptions(att_key)->SetFloat(name, val);
}
template <typename AttributeKeyT>
bool DracoOptions<AttributeKeyT>::GetAttributeBool(const AttributeKeyT &att_key,
const std::string &name,
@ -161,6 +204,25 @@ void DracoOptions<AttributeKeyT>::SetAttributeBool(const AttributeKeyT &att_key,
GetAttributeOptions(att_key)->SetBool(name, val);
}
template <typename AttributeKeyT>
template <typename DataTypeT>
bool DracoOptions<AttributeKeyT>::GetAttributeVector(
const AttributeKey &att_key, const std::string &name, int num_dims,
DataTypeT *val) const {
const Options *const att_options = FindAttributeOptions(att_key);
if (att_options && att_options->IsOptionSet(name))
return att_options->GetVector(name, num_dims, val);
return global_options_.GetVector(name, num_dims, val);
}
template <typename AttributeKeyT>
template <typename DataTypeT>
void DracoOptions<AttributeKeyT>::SetAttributeVector(
const AttributeKey &att_key, const std::string &name, int num_dims,
const DataTypeT *val) {
GetAttributeOptions(att_key)->SetVector(name, val, num_dims);
}
template <typename AttributeKeyT>
bool DracoOptions<AttributeKeyT>::IsAttributeOptionSet(
const AttributeKey &att_key, const std::string &name) const {

View File

@ -28,6 +28,7 @@ class DecodeTest : public ::testing::Test {
DecodeTest() {}
};
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
TEST_F(DecodeTest, TestSkipAttributeTransform) {
const std::string file_name = "test_nm_quant.0.9.0.drc";
// Tests that decoders can successfully skip attribute transform.
@ -73,5 +74,6 @@ TEST_F(DecodeTest, TestSkipAttributeTransform) {
ASSERT_EQ(norm_att->data_type(), draco::DT_FLOAT32);
ASSERT_EQ(norm_att->GetAttributeTransformData(), nullptr);
}
#endif
} // namespace

View File

@ -65,6 +65,16 @@ void Encoder::SetAttributeQuantization(GeometryAttribute::Type type,
options().SetAttributeInt(type, "quantization_bits", quantization_bits);
}
void Encoder::SetAttributeExplicitQuantization(GeometryAttribute::Type type,
int quantization_bits,
int num_dims,
const float *origin,
float range) {
options().SetAttributeInt(type, "quantization_bits", quantization_bits);
options().SetAttributeVector(type, "quantization_origin", num_dims, origin);
options().SetAttributeFloat(type, "quantization_range", range);
}
void Encoder::SetEncodingMethod(int encoding_method) {
Base::SetEncodingMethod(encoding_method);
}

View File

@ -75,6 +75,14 @@ class Encoder
void SetAttributeQuantization(GeometryAttribute::Type type,
int quantization_bits);
// Sets the explicit quantization compression for a named attribute. The
// attribute values will be quantized in a coordinate system defined by the
// provided origin and range (the input values should be within interval:
// <origin, origin + range>).
void SetAttributeExplicitQuantization(GeometryAttribute::Type type,
int quantization_bits, int num_dims,
const float *origin, float range);
// Sets the desired prediction method for a given attribute. By default,
// prediction scheme is selected automatically by the encoder using other
// provided options (such as speed) and input geometry type (mesh, point

View File

@ -28,6 +28,7 @@ class EncoderBase {
EncoderBase() : options_(EncoderOptionsT::CreateDefaultOptions()) {}
const EncoderOptionsT &options() const { return options_; }
EncoderOptionsT &options() { return options_; }
protected:
void Reset(const EncoderOptionsT &options) { options_ = options; }
@ -42,8 +43,6 @@ class EncoderBase {
options_.SetGlobalInt("encoding_method", encoding_method);
}
EncoderOptionsT &options() { return options_; }
private:
EncoderOptionsT options_;
};

View File

@ -124,6 +124,18 @@ void ExpertEncoder::SetAttributeQuantization(int32_t attribute_id,
quantization_bits);
}
void ExpertEncoder::SetAttributeExplicitQuantization(int32_t attribute_id,
int quantization_bits,
int num_dims,
const float *origin,
float range) {
options().SetAttributeInt(attribute_id, "quantization_bits",
quantization_bits);
options().SetAttributeVector(attribute_id, "quantization_origin", num_dims,
origin);
options().SetAttributeFloat(attribute_id, "quantization_range", range);
}
void ExpertEncoder::SetUseBuiltInAttributeCompression(bool enabled) {
options().SetGlobalBool("use_built_in_attribute_compression", enabled);
}

View File

@ -34,8 +34,8 @@ class ExpertEncoder : public EncoderBase<EncoderOptions> {
typedef EncoderBase<EncoderOptions> Base;
typedef EncoderOptions OptionsType;
ExpertEncoder(const PointCloud &point_cloud);
ExpertEncoder(const Mesh &mesh);
explicit ExpertEncoder(const PointCloud &point_cloud);
explicit ExpertEncoder(const Mesh &mesh);
// Encodes the geometry provided in the constructor to the target buffer.
Status EncodeToBuffer(EncoderBuffer *out_buffer);
@ -67,6 +67,14 @@ class ExpertEncoder : public EncoderBase<EncoderOptions> {
// on the scale of the attribute values.
void SetAttributeQuantization(int32_t attribute_id, int quantization_bits);
// Sets the explicit quantization compression for a named attribute. The
// attribute values will be quantized in a coordinate system defined by the
// provided origin and range (the input values should be within interval:
// <origin, origin + range>).
void SetAttributeExplicitQuantization(int32_t attribute_id,
int quantization_bits, int num_dims,
const float *origin, float range);
// Enables/disables built in entropy coding of attribute values. Disabling
// this option may be useful to improve the performance when third party
// compression is used on top of the Draco compression. Default: [true].

View File

@ -30,18 +30,20 @@ bool MeshEdgeBreakerDecoder::InitializeDecoder() {
if (!buffer()->Decode(&traversal_decoder_type))
return false;
impl_ = nullptr;
if (traversal_decoder_type == 0) {
if (traversal_decoder_type == MESH_EDGEBREAKER_STANDARD_ENCODING) {
#ifdef DRACO_STANDARD_EDGEBREAKER_SUPPORTED
impl_ = std::unique_ptr<MeshEdgeBreakerDecoderImplInterface>(
new MeshEdgeBreakerDecoderImpl<MeshEdgeBreakerTraversalDecoder>());
#endif
} else if (traversal_decoder_type == 1) {
} else if (traversal_decoder_type == MESH_EDGEBREAKER_PREDICTIVE_ENCODING) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
#ifdef DRACO_PREDICTIVE_EDGEBREAKER_SUPPORTED
impl_ = std::unique_ptr<MeshEdgeBreakerDecoderImplInterface>(
new MeshEdgeBreakerDecoderImpl<
MeshEdgeBreakerTraversalPredictiveDecoder>());
#endif
} else if (traversal_decoder_type == 2) {
#endif
} else if (traversal_decoder_type == MESH_EDGEBREAKER_VALENCE_ENCODING) {
impl_ = std::unique_ptr<MeshEdgeBreakerDecoderImplInterface>(
new MeshEdgeBreakerDecoderImpl<
MeshEdgeBreakerTraversalValenceDecoder>());

View File

@ -210,14 +210,15 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::CreateAttributesDecoder(
std::unique_ptr<SequentialAttributeDecodersController> att_controller(
new SequentialAttributeDecodersController(std::move(sequencer)));
decoder_->SetAttributesDecoder(att_decoder_id, std::move(att_controller));
return true;
return decoder_->SetAttributesDecoder(att_decoder_id,
std::move(att_controller));
}
template <class TraversalDecoder>
bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
num_new_vertices_ = 0;
new_to_parent_vertex_map_.clear();
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
uint32_t num_new_verts;
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
@ -229,22 +230,29 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
}
num_new_vertices_ = num_new_verts;
}
#endif
uint32_t num_encoded_vertices;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
if (!decoder_->buffer()->Decode(&num_encoded_vertices))
return false;
} else {
} else
#endif
{
if (!DecodeVarint(&num_encoded_vertices, decoder_->buffer()))
return false;
}
num_encoded_vertices_ = num_encoded_vertices;
uint32_t num_faces;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
if (!decoder_->buffer()->Decode(&num_faces))
return false;
} else {
} else
#endif
{
if (!DecodeVarint(&num_faces, decoder_->buffer()))
return false;
}
@ -279,10 +287,13 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
attribute_data_.resize(num_attribute_data);
uint32_t num_encoded_symbols;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
if (!decoder_->buffer()->Decode(&num_encoded_symbols))
return false;
} else {
} else
#endif
{
if (!DecodeVarint(&num_encoded_symbols, decoder_->buffer()))
return false;
}
@ -295,10 +306,13 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
}
uint32_t num_encoded_split_symbols;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
if (!decoder_->buffer()->Decode(&num_encoded_split_symbols))
return false;
} else {
} else
#endif
{
if (!DecodeVarint(&num_encoded_split_symbols, decoder_->buffer()))
return false;
}
@ -310,6 +324,7 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
// process (these extra vertices are then eliminated during deduplication).
is_vert_hole_.assign(num_encoded_vertices_ + num_encoded_split_symbols, true);
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
int32_t topology_split_decoded_bytes = -1;
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
uint32_t encoded_connectivity_size;
@ -330,15 +345,20 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
DecodeHoleAndTopologySplitEvents(&event_buffer);
if (topology_split_decoded_bytes == -1)
return false;
} else {
} else
#endif
{
if (DecodeHoleAndTopologySplitEvents(decoder_->buffer()) == -1)
return false;
}
traversal_decoder_.Init(this);
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_);
} else {
} else
#endif
{
// Add one extra vertex for each split symbol.
traversal_decoder_.SetNumEncodedVertices(num_encoded_vertices_ +
num_encoded_split_symbols);
@ -358,19 +378,24 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity() {
traversal_end_buffer.remaining_size(),
decoder_->buffer()->bitstream_version());
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
// Skip topology split data that was already decoded earlier.
decoder_->buffer()->Advance(topology_split_decoded_bytes);
}
#endif
// Decode connectivity of non-position attributes.
if (attribute_data_.size() > 0) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
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 {
} else
#endif
{
for (CornerIndex ci(0); ci < corner_table_->num_corners(); ci += 3) {
if (!DecodeAttributeConnectivitiesOnFace(ci))
return false;
@ -680,6 +705,11 @@ int MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeConnectivity(
// \ / \b/ \ /
// *-------*-------*
//
if (num_faces >= corner_table_->num_faces()) {
return -1; // More faces than expected added to the mesh.
}
// TODO(ostava): The circulation below should be replaced by functions
// that can be reused elsewhere.
CornerIndex corner_b = corner_table_->Previous(corner);
@ -732,15 +762,34 @@ MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
DecoderBuffer *decoder_buffer) {
// Prepare a new decoder from the provided buffer offset.
uint32_t num_topology_splits;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
if (!decoder_buffer->Decode(&num_topology_splits))
return -1;
} else {
} else
#endif
{
if (!DecodeVarint(&num_topology_splits, decoder_buffer))
return -1;
}
if (num_topology_splits > 0) {
if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
for (uint32_t i = 0; i < num_topology_splits; ++i) {
TopologySplitEventData event_data;
if (!decoder_buffer->Decode(&event_data.split_symbol_id))
return -1;
if (!decoder_buffer->Decode(&event_data.source_symbol_id))
return -1;
uint8_t edge_data;
if (!decoder_buffer->Decode(&edge_data))
return -1;
event_data.source_edge = edge_data & 1;
topology_split_data_.push_back(event_data);
}
} else
#endif
{
// Decode source and split symbol ids using delta and varint coding. See
// description in mesh_edgebreaker_encoder_impl.cc for more details.
int last_source_symbol_id = 0;
@ -750,6 +799,8 @@ MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
DecodeVarint<uint32_t>(&delta, decoder_buffer);
event_data.source_symbol_id = delta + last_source_symbol_id;
DecodeVarint<uint32_t>(&delta, decoder_buffer);
if (delta > event_data.source_symbol_id)
return -1;
event_data.split_symbol_id =
event_data.source_symbol_id - static_cast<int32_t>(delta);
last_source_symbol_id = event_data.source_symbol_id;
@ -768,22 +819,10 @@ MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
event_data.source_edge = edge_data & 1;
}
decoder_buffer->EndBitDecoding();
} else {
for (uint32_t i = 0; i < num_topology_splits; ++i) {
TopologySplitEventData event_data;
if (!decoder_buffer->Decode(&event_data.split_symbol_id))
return -1;
if (!decoder_buffer->Decode(&event_data.source_symbol_id))
return -1;
uint8_t edge_data;
if (!decoder_buffer->Decode(&edge_data))
return -1;
event_data.source_edge = edge_data & 1;
topology_split_data_.push_back(event_data);
}
}
}
uint32_t num_hole_events = 0;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
if (!decoder_buffer->Decode(&num_hole_events))
return -1;
@ -791,8 +830,19 @@ MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
if (!DecodeVarint(&num_hole_events, decoder_buffer))
return -1;
}
#endif
if (num_hole_events > 0) {
if (decoder_->bitstream_version() >= DRACO_BITSTREAM_VERSION(1, 2)) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (decoder_->bitstream_version() < DRACO_BITSTREAM_VERSION(1, 2)) {
for (uint32_t i = 0; i < num_hole_events; ++i) {
HoleEventData event_data;
if (!decoder_buffer->Decode(&event_data))
return -1;
hole_event_data_.push_back(event_data);
}
} else
#endif
{
// Decode hole symbol ids using delta and varint coding.
int last_symbol_id = 0;
for (uint32_t i = 0; i < num_hole_events; ++i) {
@ -803,18 +853,12 @@ MeshEdgeBreakerDecoderImpl<TraversalDecoder>::DecodeHoleAndTopologySplitEvents(
last_symbol_id = event_data.symbol_id;
hole_event_data_.push_back(event_data);
}
} else {
for (uint32_t i = 0; i < num_hole_events; ++i) {
HoleEventData event_data;
if (!decoder_buffer->Decode(&event_data))
return -1;
hole_event_data_.push_back(event_data);
}
}
}
return decoder_buffer->decoded_size();
}
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
template <class TraversalDecoder>
bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::
DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner) {
@ -841,6 +885,7 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::
}
return true;
}
#endif
template <class TraversalDecoder>
bool MeshEdgeBreakerDecoderImpl<
@ -996,8 +1041,10 @@ bool MeshEdgeBreakerDecoderImpl<TraversalDecoder>::AssignPointsToCorners() {
}
template class MeshEdgeBreakerDecoderImpl<MeshEdgeBreakerTraversalDecoder>;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
template class MeshEdgeBreakerDecoderImpl<
MeshEdgeBreakerTraversalPredictiveDecoder>;
#endif
template class MeshEdgeBreakerDecoderImpl<
MeshEdgeBreakerTraversalValenceDecoder>;
} // namespace draco

View File

@ -111,7 +111,9 @@ class MeshEdgeBreakerDecoderImpl : public MeshEdgeBreakerDecoderImplInterface {
// Decodes all non-position attribute connectivity on the currently
// processed face.
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
bool DecodeAttributeConnectivitiesOnFaceLegacy(CornerIndex corner);
#endif
bool DecodeAttributeConnectivitiesOnFace(CornerIndex corner);
// Initializes mapping between corners and point ids.

View File

@ -23,9 +23,9 @@ namespace draco {
MeshEdgeBreakerEncoder::MeshEdgeBreakerEncoder() {}
bool MeshEdgeBreakerEncoder::InitializeEncoder() {
const bool is_standard_edgebreaker_avaialable =
const bool is_standard_edgebreaker_available =
options()->IsFeatureSupported(features::kEdgebreaker);
const bool is_predictive_edgebreaker_avaialable =
const bool is_predictive_edgebreaker_available =
options()->IsFeatureSupported(features::kPredictiveEdgebreaker);
impl_ = nullptr;
@ -36,14 +36,27 @@ bool MeshEdgeBreakerEncoder::InitializeEncoder() {
// needed.
const bool is_tiny_mesh = mesh()->num_faces() < 1000;
if (is_standard_edgebreaker_avaialable &&
(options()->GetSpeed() >= 5 || !is_predictive_edgebreaker_avaialable ||
is_tiny_mesh)) {
buffer()->Encode(static_cast<uint8_t>(0));
impl_ = std::unique_ptr<MeshEdgeBreakerEncoderImplInterface>(
new MeshEdgeBreakerEncoderImpl<MeshEdgeBreakerTraversalEncoder>());
} else if (is_predictive_edgebreaker_avaialable) {
buffer()->Encode(static_cast<uint8_t>(2));
int selected_edgebreaker_method =
options()->GetGlobalInt("edgebreaker_method", -1);
if (selected_edgebreaker_method == -1) {
if (is_standard_edgebreaker_available &&
(options()->GetSpeed() >= 5 || !is_predictive_edgebreaker_available ||
is_tiny_mesh)) {
selected_edgebreaker_method = MESH_EDGEBREAKER_STANDARD_ENCODING;
} else {
selected_edgebreaker_method = MESH_EDGEBREAKER_VALENCE_ENCODING;
}
}
if (selected_edgebreaker_method == MESH_EDGEBREAKER_STANDARD_ENCODING) {
if (is_standard_edgebreaker_available) {
buffer()->Encode(
static_cast<uint8_t>(MESH_EDGEBREAKER_STANDARD_ENCODING));
impl_ = std::unique_ptr<MeshEdgeBreakerEncoderImplInterface>(
new MeshEdgeBreakerEncoderImpl<MeshEdgeBreakerTraversalEncoder>());
}
} else if (selected_edgebreaker_method == MESH_EDGEBREAKER_VALENCE_ENCODING) {
buffer()->Encode(static_cast<uint8_t>(MESH_EDGEBREAKER_VALENCE_ENCODING));
impl_ = std::unique_ptr<MeshEdgeBreakerEncoderImplInterface>(
new MeshEdgeBreakerEncoderImpl<
MeshEdgeBreakerTraversalValenceEncoder>());

View File

@ -34,7 +34,8 @@ template <class TraversalEncoderT>
class MeshEdgeBreakerEncoderImpl : public MeshEdgeBreakerEncoderImplInterface {
public:
MeshEdgeBreakerEncoderImpl();
MeshEdgeBreakerEncoderImpl(const TraversalEncoderT &traversal_encoder);
explicit MeshEdgeBreakerEncoderImpl(
const TraversalEncoderT &traversal_encoder);
bool Init(MeshEdgeBreakerEncoder *encoder) override;
const MeshAttributeCornerTable *GetAttributeCornerTable(

View File

@ -73,9 +73,12 @@ class MeshEdgeBreakerTraversalDecoder {
// Returns the configuration of a new initial face.
inline bool DecodeStartFaceConfiguration() {
uint32_t face_configuration;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
start_face_buffer_.DecodeLeastSignificantBits32(1, &face_configuration);
} else {
} else
#endif
{
face_configuration = start_face_decoder_.DecodeNextBit();
}
return face_configuration;
@ -114,9 +117,12 @@ class MeshEdgeBreakerTraversalDecoder {
void Done() {
if (symbol_buffer_.bit_decoder_active())
symbol_buffer_.EndBitDecoding();
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
start_face_buffer_.EndBitDecoding();
} else {
} else
#endif
{
start_face_decoder_.EndDecoding();
}
}
@ -138,6 +144,7 @@ class MeshEdgeBreakerTraversalDecoder {
bool DecodeStartFaces() {
// Create a decoder that is set to the end of the encoded traversal data.
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (buffer_.bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
start_face_buffer_ = buffer_;
uint64_t traversal_size;
@ -147,7 +154,9 @@ class MeshEdgeBreakerTraversalDecoder {
if (traversal_size > buffer_.remaining_size())
return false;
buffer_.Advance(traversal_size);
} else {
} else
#endif
{
start_face_decoder_.StartDecoding(&buffer_);
}
return true;

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
#ifndef DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_PREDICTIVE_DECODER_H_
#define DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_PREDICTIVE_DECODER_H_
@ -126,3 +127,4 @@ class MeshEdgeBreakerTraversalPredictiveDecoder
} // namespace draco
#endif // DRACO_COMPRESSION_MESH_MESH_EDGEBREAKER_TRAVERSAL_PREDICTIVE_DECODER_H_
#endif

View File

@ -42,16 +42,19 @@ class MeshEdgeBreakerTraversalValenceDecoder
void SetNumEncodedVertices(int num_vertices) { num_vertices_ = num_vertices; }
bool Start(DecoderBuffer *out_buffer) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) {
if (!MeshEdgeBreakerTraversalDecoder::DecodeTraversalSymbols())
return false;
}
#endif
if (!MeshEdgeBreakerTraversalDecoder::DecodeStartFaces())
return false;
if (!MeshEdgeBreakerTraversalDecoder::DecodeAttributeSeams())
return false;
*out_buffer = *buffer();
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) {
uint32_t num_split_symbols;
if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 0)) {
@ -74,11 +77,15 @@ class MeshEdgeBreakerTraversalValenceDecoder
// Unsupported mode.
return false;
}
} else {
} else
#endif
{
min_valence_ = 2;
max_valence_ = 7;
}
if (num_vertices_ < 0)
return false;
// Set the valences of all initial vertices to 0.
vertex_valences_.resize(num_vertices_, 0);
@ -103,16 +110,20 @@ class MeshEdgeBreakerTraversalValenceDecoder
inline uint32_t DecodeSymbol() {
// First check if we have a valid context.
if (active_context_ != -1) {
const int symbol_id =
context_symbols_[active_context_]
[--context_counters_[active_context_]];
const int context_counter = --context_counters_[active_context_];
if (context_counter < 0)
return TOPOLOGY_INVALID;
const int symbol_id = context_symbols_[active_context_][context_counter];
last_symbol_ = edge_breaker_symbol_to_topology_id[symbol_id];
} else {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (BitstreamVersion() < DRACO_BITSTREAM_VERSION(2, 2)) {
// We don't have a predicted symbol or the symbol was mis-predicted.
// Decode it directly.
last_symbol_ = MeshEdgeBreakerTraversalDecoder::DecodeSymbol();
} else {
} else
#endif
{
// The first symbol must be E.
last_symbol_ = TOPOLOGY_E;
}

View File

@ -85,9 +85,8 @@ TEST_P(MeshEncoderTest, EncodeGoldenMesh) {
EXPECT_TRUE(
CompareGoldenFile(golden_file_name, buffer.data(), buffer.size()))
<< "Encoded data is different from the golden file. Please verify that "
"the"
" encoding works as expected and update the golden file if necessary"
" (run the test with --update_golden_files flag).";
"the encoding works as expected and update the golden file if "
"necessary (run the test with --update_golden_files flag).";
} else {
// Save the files into the local folder.
EXPECT_TRUE(

View File

@ -26,12 +26,15 @@ MeshSequentialDecoder::MeshSequentialDecoder() {}
bool MeshSequentialDecoder::DecodeConnectivity() {
uint32_t num_faces;
uint32_t num_points;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
if (!buffer()->Decode(&num_faces))
return false;
if (!buffer()->Decode(&num_points))
return false;
} else {
} else
#endif
{
if (!DecodeVarint(&num_faces, buffer()))
return false;
if (!DecodeVarint(&num_points, buffer()))
@ -41,8 +44,8 @@ bool MeshSequentialDecoder::DecodeConnectivity() {
// Check that num_faces and num_points are valid values.
const uint64_t faces_64 = static_cast<uint64_t>(num_faces);
const uint64_t points_64 = static_cast<uint64_t>(num_points);
// Compressed sequential encoding can only handle 2^31 indices.
if (faces_64 > 0x7fffffff)
// Compressed sequential encoding can only handle (2^32 - 1) / 3 indices.
if (faces_64 > 0xffffffff / 3)
return false;
if (points_64 > faces_64 * 3)
return false;
@ -110,16 +113,15 @@ bool MeshSequentialDecoder::DecodeConnectivity() {
bool MeshSequentialDecoder::CreateAttributesDecoder(int32_t att_decoder_id) {
// Always create the basic attribute decoder.
SetAttributesDecoder(
return SetAttributesDecoder(
att_decoder_id,
std::unique_ptr<AttributesDecoder>(
new SequentialAttributeDecodersController(
std::unique_ptr<PointsSequencer>(
new LinearSequencer(point_cloud()->num_points())))));
return true;
}
bool MeshSequentialDecoder::DecodeAndDecompressIndices(int32_t num_faces) {
bool MeshSequentialDecoder::DecodeAndDecompressIndices(uint32_t num_faces) {
// Get decoded indices differences that were encoded with an entropy code.
std::vector<uint32_t> indices_buffer(num_faces * 3);
if (!DecodeSymbols(num_faces * 3, 1, buffer(), indices_buffer.data()))

View File

@ -31,7 +31,7 @@ class MeshSequentialDecoder : public MeshDecoder {
private:
// Decodes face indices that were compressed with an entropy code.
// Returns false on error.
bool DecodeAndDecompressIndices(int32_t num_faces);
bool DecodeAndDecompressIndices(uint32_t num_faces);
};
} // namespace draco

View File

@ -80,7 +80,7 @@ class DynamicIntegerPointsKdTreeDecoder {
typedef std::vector<uint32_t> VectorUint32;
public:
DynamicIntegerPointsKdTreeDecoder(uint32_t dimension)
explicit DynamicIntegerPointsKdTreeDecoder(uint32_t dimension)
: bit_length_(0),
dimension_(dimension),
p_(dimension, 0),

View File

@ -99,7 +99,7 @@ class DynamicIntegerPointsKdTreeEncoder {
typedef std::vector<uint32_t> VectorUint32;
public:
DynamicIntegerPointsKdTreeEncoder(uint32_t dimension)
explicit DynamicIntegerPointsKdTreeEncoder(uint32_t dimension)
: bit_length_(0),
dimension_(dimension),
deviations_(dimension, 0),

View File

@ -17,6 +17,7 @@
#include <memory>
#include "draco/compression/config/compression_shared.h"
#include "draco/compression/point_cloud/algorithms/point_cloud_compression_method.h"
#include "draco/compression/point_cloud/algorithms/point_cloud_types.h"
#include "draco/compression/point_cloud/algorithms/quantize_points_3.h"
@ -41,6 +42,7 @@ class FloatPointsTreeDecoder {
DecoderBuffer buffer;
buffer.Init(data, data_size);
buffer.set_bitstream_version(kDracoBitstreamVersion);
return DecodePointCloud(&buffer, out);
}

View File

@ -47,7 +47,7 @@ namespace draco {
// TODO(hemmer): Remove class because it duplicates quantization code.
class FloatPointsTreeEncoder {
public:
FloatPointsTreeEncoder(PointCloudCompressionMethod method);
explicit FloatPointsTreeEncoder(PointCloudCompressionMethod method);
explicit FloatPointsTreeEncoder(PointCloudCompressionMethod method,
uint32_t quantization_bits,
uint32_t compression_level);

View File

@ -28,6 +28,8 @@ typedef Vector4f Point4f;
typedef Vector3ui Point3ui;
typedef Vector4ui Point4ui;
typedef Vector5ui Point5ui;
typedef Vector6ui Point6ui;
typedef Vector7ui Point7ui;
typedef std::vector<Point3f> PointCloud3f;

View File

@ -40,11 +40,14 @@ class PointCloudDecoder {
Status Decode(const DecoderOptions &options, DecoderBuffer *in_buffer,
PointCloud *out_point_cloud);
void SetAttributesDecoder(
bool SetAttributesDecoder(
int att_decoder_id, std::unique_ptr<AttributesDecoderInterface> decoder) {
if (att_decoder_id < 0)
return false;
if (att_decoder_id >= static_cast<int>(attributes_decoders_.size()))
attributes_decoders_.resize(att_decoder_id + 1);
attributes_decoders_[att_decoder_id] = std::move(decoder);
return true;
}
// Returns an attribute containing decoded data in their portable form that

View File

@ -28,9 +28,9 @@ bool PointCloudKdTreeDecoder::DecodeGeometryData() {
bool PointCloudKdTreeDecoder::CreateAttributesDecoder(int32_t att_decoder_id) {
// Always create the basic attribute decoder.
SetAttributesDecoder(att_decoder_id, std::unique_ptr<AttributesDecoder>(
new KdTreeAttributesDecoder()));
return true;
return SetAttributesDecoder(
att_decoder_id,
std::unique_ptr<AttributesDecoder>(new KdTreeAttributesDecoder()));
}
} // namespace draco

View File

@ -30,13 +30,12 @@ bool PointCloudSequentialDecoder::DecodeGeometryData() {
bool PointCloudSequentialDecoder::CreateAttributesDecoder(
int32_t att_decoder_id) {
// Always create the basic attribute decoder.
SetAttributesDecoder(
return SetAttributesDecoder(
att_decoder_id,
std::unique_ptr<AttributesDecoder>(
new SequentialAttributeDecodersController(
std::unique_ptr<PointsSequencer>(
new LinearSequencer(point_cloud()->num_points())))));
return true;
}
} // namespace draco

View File

@ -31,10 +31,13 @@ bool RAnsBitDecoder::StartDecoding(DecoderBuffer *source_buffer) {
return false;
uint32_t size_in_bytes;
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (source_buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 2)) {
if (!source_buffer->Decode(&size_in_bytes))
return false;
} else {
} else
#endif
{
if (!DecodeVarint(&size_in_bytes, source_buffer))
return false;
}

View File

@ -23,7 +23,7 @@
#if defined(_MSC_VER)
#include <intrin.h>
#endif // defined(_MSC_VER)
#endif // defined(_MSC_VER)
namespace draco {
namespace bits {

View File

@ -39,10 +39,13 @@ void DecoderBuffer::Init(const char *data, size_t data_size, uint16_t version) {
bool DecoderBuffer::StartBitDecoding(bool decode_size, uint64_t *out_size) {
if (decode_size) {
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (bitstream_version_ < DRACO_BITSTREAM_VERSION(2, 2)) {
if (!Decode(out_size))
return false;
} else {
} else
#endif
{
if (!DecodeVarint(out_size, this))
return false;
}

View File

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

View File

@ -17,24 +17,20 @@
#include <cstdlib>
#include <string>
namespace {
std::string ValToString(int val) {
char temp[64];
sprintf(temp, "%d", val);
return temp;
}
} // namespace
namespace draco {
Options::Options() {}
void Options::SetInt(const std::string &name, int val) {
options_[name] = ValToString(val);
options_[name] = std::to_string(val);
}
void Options::SetFloat(const std::string &name, float val) {
options_[name] = std::to_string(val);
}
void Options::SetBool(const std::string &name, bool val) {
options_[name] = ValToString(val ? 1 : 0);
options_[name] = std::to_string(val ? 1 : 0);
}
void Options::SetString(const std::string &name, const std::string &val) {
@ -50,6 +46,17 @@ int Options::GetInt(const std::string &name, int default_val) const {
return std::atoi(it->second.c_str());
}
float Options::GetFloat(const std::string &name) const {
return GetFloat(name, -1);
}
float Options::GetFloat(const std::string &name, float default_val) const {
const auto it = options_.find(name);
if (it == options_.end())
return default_val;
return std::atof(it->second.c_str());
}
bool Options::GetBool(const std::string &name) const {
return GetBool(name, false);
}

View File

@ -29,6 +29,7 @@ class Options {
public:
Options();
void SetInt(const std::string &name, int val);
void SetFloat(const std::string &name, float val);
void SetBool(const std::string &name, bool val);
void SetString(const std::string &name, const std::string &val);
template <class VectorT>
@ -42,18 +43,21 @@ class Options {
// value can be specified in the overloaded version of each function.
int GetInt(const std::string &name) const;
int GetInt(const std::string &name, int default_val) const;
float GetFloat(const std::string &name) const;
float GetFloat(const std::string &name, float default_val) const;
bool GetBool(const std::string &name) const;
bool GetBool(const std::string &name, bool default_val) const;
std::string GetString(const std::string &name) const;
std::string GetString(const std::string &name,
const std::string &default_val) const;
template <class VectorT>
VectorT GetVector(const std::string &name, const VectorT &default_val);
VectorT GetVector(const std::string &name, const VectorT &default_val) const;
// Unlike other Get functions, this function returns false if the option does
// not exist, otherwise it fills |out_val| with the vector values. If a
// default value is needed, it can be set in |out_val|.
template <typename DataTypeT>
bool GetVector(const std::string &name, int num_dims, DataTypeT *out_val);
bool GetVector(const std::string &name, int num_dims,
DataTypeT *out_val) const;
bool IsOptionSet(const std::string &name) const {
return options_.count(name) > 0;
@ -74,14 +78,18 @@ void Options::SetVector(const std::string &name, const DataTypeT *vec,
for (int i = 0; i < num_dims; ++i) {
if (i > 0)
out += " ";
#ifdef ANDROID
out += to_string(vec[i]);
#else
out += std::to_string(vec[i]);
#endif
}
options_[name] = out;
}
template <class VectorT>
VectorT Options::GetVector(const std::string &name,
const VectorT &default_val) {
const VectorT &default_val) const {
VectorT ret = default_val;
GetVector(name, VectorT::dimension, &ret[0]);
return ret;
@ -89,23 +97,32 @@ VectorT Options::GetVector(const std::string &name,
template <typename DataTypeT>
bool Options::GetVector(const std::string &name, int num_dims,
DataTypeT *out_val) {
if (!IsOptionSet(name))
DataTypeT *out_val) const {
const auto it = options_.find(name);
if (it == options_.end())
return false;
std::string value = options_[name];
const std::string value = it->second;
if (value.length() == 0)
return true; // Option set but no data is present
const char *act_str = value.c_str();
char *next_str;
for (int i = 0; i < num_dims; ++i) {
if (std::is_integral<DataTypeT>::value) {
#ifdef ANDROID
const int val = strtol(act_str, &next_str, 10);
#else
const int val = std::strtol(act_str, &next_str, 10);
#endif
if (act_str == next_str)
return true; // End reached.
act_str = next_str;
out_val[i] = static_cast<DataTypeT>(val);
} else {
#ifdef ANDROID
const float val = strtof(act_str, &next_str);
#else
const float val = std::strtof(act_str, &next_str);
#endif
if (act_str == next_str)
return true; // End reached.
act_str = next_str;

View File

@ -25,9 +25,12 @@ void Quantizer::Init(float range, int32_t max_quantized_value) {
Dequantizer::Dequantizer() : range_(1.f), max_quantized_value_factor_(1.f) {}
void Dequantizer::Init(float range, int32_t max_quantized_value) {
bool Dequantizer::Init(float range, int32_t max_quantized_value) {
if (max_quantized_value <= 0)
return false;
max_quantized_value_factor_ = 1.f / static_cast<float>(max_quantized_value);
range_ = range;
return true;
}
} // namespace draco

View File

@ -62,7 +62,8 @@ class Dequantizer {
// Initializes the dequantizer. Both parameters must correspond to the values
// provided to the initializer of the Quantizer class.
void Init(float range, int32_t max_quantized_value);
// Returns false when the initialization fails.
bool Init(float range, int32_t max_quantized_value);
inline float DequantizeFloat(int32_t val) const {
const bool neg = (val < 0);
if (neg) {

View File

@ -41,11 +41,16 @@ TEST_F(QuantizationUtilsTest, TestQuantizer) {
TEST_F(QuantizationUtilsTest, TestDequantizer) {
Dequantizer dequantizer;
dequantizer.Init(10.f, 255);
ASSERT_TRUE(dequantizer.Init(10.f, 255));
EXPECT_EQ(dequantizer.DequantizeFloat(0), 0.f);
EXPECT_EQ(dequantizer.DequantizeFloat(255), 10.f);
EXPECT_EQ(dequantizer.DequantizeFloat(-255), -10.f);
EXPECT_EQ(dequantizer.DequantizeFloat(128), 10.f * (128.f / 255.f));
// Test that the dequantizer fails to initialize with invalid input
// parameters.
ASSERT_FALSE(dequantizer.Init(1.f, 0));
ASSERT_FALSE(dequantizer.Init(1.f, -4));
}
} // namespace draco

View File

@ -58,11 +58,14 @@ bool RAnsSymbolDecoder<max_symbol_bit_length_t>::Create(DecoderBuffer *buffer) {
// Check that the DecoderBuffer version is set.
if (buffer->bitstream_version() == 0)
return false;
// Decode the number of alphabet symbols.
// Decode the number of alphabet symbols.
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
if (!buffer->Decode(&num_symbols_))
return false;
} else {
} else
#endif
{
if (!DecodeVarint(&num_symbols_, buffer))
return false;
}
@ -114,10 +117,13 @@ bool RAnsSymbolDecoder<max_symbol_bit_length_t>::StartDecoding(
DecoderBuffer *buffer) {
uint64_t bytes_encoded;
// Decode the number of bytes encoded by the encoder.
#ifdef DRACO_BACKWARDS_COMPATIBILITY_SUPPORTED
if (buffer->bitstream_version() < DRACO_BITSTREAM_VERSION(2, 0)) {
if (!buffer->Decode(&bytes_encoded))
return false;
} else {
} else
#endif
{
if (!DecodeVarint<uint64_t>(&bytes_encoded, buffer))
return false;
}

View File

@ -36,7 +36,7 @@ class Status {
Status() : code_(OK) {}
Status(const Status &status) = default;
Status(Status &&status) = default;
Status(Code code) : code_(code) {}
explicit Status(Code code) : code_(code) {}
Status(Code code, const std::string &error_msg)
: code_(code), error_msg_(error_msg) {}

View File

@ -22,17 +22,15 @@
namespace draco {
template <template <int> class SymbolDecoderT>
bool DecodeTaggedSymbols(int num_values, int num_components,
bool DecodeTaggedSymbols(uint32_t num_values, int num_components,
DecoderBuffer *src_buffer, uint32_t *out_values);
template <template <int> class SymbolDecoderT>
bool DecodeRawSymbols(int num_values, DecoderBuffer *src_buffer,
bool DecodeRawSymbols(uint32_t num_values, DecoderBuffer *src_buffer,
uint32_t *out_values);
bool DecodeSymbols(int num_values, int num_components,
bool DecodeSymbols(uint32_t num_values, int num_components,
DecoderBuffer *src_buffer, uint32_t *out_values) {
if (num_values < 0)
return false;
if (num_values == 0)
return true;
// Decode which scheme to use.
@ -50,7 +48,7 @@ bool DecodeSymbols(int num_values, int num_components,
}
template <template <int> class SymbolDecoderT>
bool DecodeTaggedSymbols(int num_values, int num_components,
bool DecodeTaggedSymbols(uint32_t num_values, int num_components,
DecoderBuffer *src_buffer, uint32_t *out_values) {
// Decode the encoded data.
SymbolDecoderT<5> tag_decoder;
@ -84,7 +82,7 @@ bool DecodeTaggedSymbols(int num_values, int num_components,
}
template <class SymbolDecoderT>
bool DecodeRawSymbolsInternal(int num_values, DecoderBuffer *src_buffer,
bool DecodeRawSymbolsInternal(uint32_t num_values, DecoderBuffer *src_buffer,
uint32_t *out_values) {
SymbolDecoderT decoder;
if (!decoder.Create(src_buffer))
@ -95,7 +93,7 @@ bool DecodeRawSymbolsInternal(int num_values, DecoderBuffer *src_buffer,
if (!decoder.StartDecoding(src_buffer))
return false;
for (int i = 0; i < num_values; ++i) {
for (uint32_t i = 0; i < num_values; ++i) {
// Decode a symbol into the value.
const uint32_t value = decoder.DecodeSymbol();
out_values[i] = value;
@ -105,7 +103,7 @@ bool DecodeRawSymbolsInternal(int num_values, DecoderBuffer *src_buffer,
}
template <template <int> class SymbolDecoderT>
bool DecodeRawSymbols(int num_values, DecoderBuffer *src_buffer,
bool DecodeRawSymbols(uint32_t num_values, DecoderBuffer *src_buffer,
uint32_t *out_values) {
uint8_t max_bit_length;
if (!src_buffer->Decode(&max_bit_length))

View File

@ -21,7 +21,7 @@ namespace draco {
// Decodes an array of symbols that was previously encoded with an entropy code.
// Returns false on error.
bool DecodeSymbols(int num_values, int num_components,
bool DecodeSymbols(uint32_t num_values, int num_components,
DecoderBuffer *src_buffer, uint32_t *out_values);
} // namespace draco

View File

@ -209,10 +209,12 @@ bool ObjDecoder::DecodeInternal() {
out_mesh_->SetFace(i, face);
}
}
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
if (deduplicate_input_values_) {
out_point_cloud_->DeduplicateAttributeValues();
}
out_point_cloud_->DeduplicatePointIds();
#endif
return true;
}

View File

@ -69,6 +69,7 @@ bool PlyDecoder::DecodeInternal() {
// Decode all attributes.
if (!DecodeVertexData(ply_reader.GetElementByName("vertex")))
return false;
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
// In case there are no faces this is just a point cloud which does
// not require deduplication.
if (out_mesh_ && out_mesh_->num_faces() != 0) {
@ -76,6 +77,7 @@ bool PlyDecoder::DecodeInternal() {
return false;
out_point_cloud_->DeduplicatePointIds();
}
#endif
return true;
}

View File

@ -26,7 +26,8 @@ namespace draco {
template <typename ReadTypeT>
class PlyPropertyReader {
public:
PlyPropertyReader(const PlyProperty *property) : property_(property) {
explicit PlyPropertyReader(const PlyProperty *property)
: property_(property) {
// Find the suitable function for converting values.
switch (property->data_type()) {
case DT_UINT8:

View File

@ -26,7 +26,7 @@ namespace draco {
template <typename WriteTypeT>
class PlyPropertyWriter {
public:
PlyPropertyWriter(PlyProperty *property) : property_(property) {
explicit PlyPropertyWriter(PlyProperty *property) : property_(property) {
// Find the suitable function for converting values.
switch (property->data_type()) {
case DT_UINT8:

View File

@ -110,6 +110,11 @@ interface Encoder {
void SetEncodingMethod(draco_MeshEncoderMethod method);
void SetAttributeQuantization(draco_GeometryAttribute_Type type,
long quantization_bits);
void SetAttributeExplicitQuantization(draco_GeometryAttribute_Type type,
long quantization_bits,
long num_components,
[Const] float[] origin,
float range);
void SetSpeedOptions(long encoding_speed, long decoding_speed);
long EncodeMeshToDracoBuffer(Mesh mesh,
DracoInt8Array encoded_data);

View File

@ -166,6 +166,13 @@ void Encoder::SetAttributeQuantization(draco_GeometryAttribute_Type type,
encoder_.SetAttributeQuantization(type, quantization_bits);
}
void Encoder::SetAttributeExplicitQuantization(
draco_GeometryAttribute_Type type, long quantization_bits,
long num_components, const float *origin, float range) {
encoder_.SetAttributeExplicitQuantization(type, quantization_bits,
num_components, origin, range);
}
void Encoder::SetSpeedOptions(long encoding_speed, long decoding_speed) {
encoder_.SetSpeedOptions(encoding_speed, decoding_speed);
}

View File

@ -92,6 +92,10 @@ class Encoder {
void SetEncodingMethod(draco_MeshEncoderMethod method);
void SetAttributeQuantization(draco_GeometryAttribute_Type type,
long quantization_bits);
void SetAttributeExplicitQuantization(draco_GeometryAttribute_Type type,
long quantization_bits,
long num_components,
const float *origin, float range);
void SetSpeedOptions(long encoding_speed, long decoding_speed);
int EncodeMeshToDracoBuffer(draco::Mesh *mesh, DracoInt8Array *buffer);

View File

@ -27,6 +27,7 @@ using conditional_t = typename std::conditional<B, T, F>::type;
Mesh::Mesh() {}
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
void Mesh::ApplyPointIdDeduplication(
const IndexTypeVector<PointIndex, PointIndex> &id_map,
const std::vector<PointIndex> &unique_point_ids) {
@ -37,5 +38,6 @@ void Mesh::ApplyPointIdDeduplication(
}
}
}
#endif
} // namespace draco

View File

@ -93,12 +93,14 @@ class Mesh : public PointCloud {
};
protected:
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
// Extends the point deduplication to face corners. This method is called from
// the PointCloud::DeduplicatePointIds() and it remaps all point ids stored in
// |faces_| to the new deduplicated point ids using the map |id_map|.
void ApplyPointIdDeduplication(
const IndexTypeVector<PointIndex, PointIndex> &id_map,
const std::vector<PointIndex> &unique_point_ids) override;
#endif
private:
// Mesh specific per-attribute data.

View File

@ -53,7 +53,8 @@ class MeshAreEquivalent {
// Less compare functor for two faces (represented by their indices)
// with respect to their lex order.
struct FaceIndexLess {
FaceIndexLess(const MeshInfo &in_mesh_info) : mesh_info(in_mesh_info) {}
explicit FaceIndexLess(const MeshInfo &in_mesh_info)
: mesh_info(in_mesh_info) {}
bool operator()(FaceIndex f0, FaceIndex f1) const;
const MeshInfo &mesh_info;
};

View File

@ -21,6 +21,9 @@
#include "draco/mesh/corner_table.h"
#include "draco/mesh/mesh.h"
// The file contains functions that use both Mesh and CornerTable as inputs.
// TODO(hemmer): We should consider moving the functionality to CornerTable.
namespace draco {
// Creates a CornerTable from the position attribute of |mesh|. Returns nullptr
@ -44,6 +47,33 @@ inline PointIndex CornerToPointId(int c, const Mesh *mesh) {
return mesh->face(FaceIndex(c / 3))[c % 3];
}
// Returns the point id of |c| without using a corner table.
inline PointIndex CornerToPointId(CornerIndex c, const Mesh *mesh) {
return CornerToPointId(c.value(), mesh);
}
// Returns true when the given corner lies opposite to an attribute seam.
inline bool IsCornerOppositeToAttributeSeam(CornerIndex ci,
const PointAttribute &att,
const Mesh &mesh,
const CornerTable &ct) {
const CornerIndex opp_ci = ct.Opposite(ci);
if (opp_ci < 0)
return false; // No opposite corner == no attribute seam.
// Compare attribute value indices on both ends of the opposite edge.
CornerIndex c0 = ct.Next(ci);
CornerIndex c1 = ct.Previous(opp_ci);
if (att.mapped_index(CornerToPointId(c0, &mesh)) !=
att.mapped_index(CornerToPointId(c1, &mesh)))
return true;
c0 = ct.Previous(ci);
c1 = ct.Next(opp_ci);
if (att.mapped_index(CornerToPointId(c0, &mesh)) !=
att.mapped_index(CornerToPointId(c1, &mesh)))
return true;
return false;
}
} // namespace draco
#endif // DRACO_MESH_MESH_MISC_FUNCTIONS_H_

View File

@ -65,11 +65,13 @@ void TriangleSoupMeshBuilder::SetPerFaceAttributeValueForFace(
}
std::unique_ptr<Mesh> TriangleSoupMeshBuilder::Finalize() {
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
// First deduplicate attribute values.
if (!mesh_->DeduplicateAttributeValues())
return nullptr;
// Also deduplicate vertex indices.
mesh_->DeduplicatePointIds();
#endif
for (size_t i = 0; i < attribute_element_types_.size(); ++i) {
if (attribute_element_types_[i] >= 0) {
mesh_->SetAttributeElementType(i, static_cast<MeshAttributeElementType>(

View File

@ -56,7 +56,7 @@ struct AttributeMetadataHasher {
class GeometryMetadata : public Metadata {
public:
GeometryMetadata(){};
GeometryMetadata(const Metadata &metadata) : Metadata(metadata) {}
explicit GeometryMetadata(const Metadata &metadata) : Metadata(metadata) {}
const AttributeMetadata *GetAttributeMetadataByStringEntry(
const std::string &entry_name, const std::string &entry_value) const;

View File

@ -31,21 +31,21 @@ namespace draco {
class EntryValue {
public:
template <typename DataTypeT>
EntryValue(const DataTypeT &data) {
explicit EntryValue(const DataTypeT &data) {
const size_t data_type_size = sizeof(DataTypeT);
data_.resize(data_type_size);
memcpy(&data_[0], &data, data_type_size);
}
template <typename DataTypeT>
EntryValue(const std::vector<DataTypeT> &data) {
explicit EntryValue(const std::vector<DataTypeT> &data) {
const size_t total_size = sizeof(DataTypeT) * data.size();
data_.resize(total_size);
memcpy(&data_[0], &data[0], total_size);
}
EntryValue(const EntryValue &value);
EntryValue(const std::string &value);
explicit EntryValue(const std::string &value);
template <typename DataTypeT>
bool GetValue(DataTypeT *value) const {
@ -147,7 +147,7 @@ class Metadata {
const auto itr = entries_.find(entry_name);
if (itr != entries_.end())
entries_.erase(itr);
entries_.insert(std::make_pair(entry_name, entry_value));
entries_.insert(std::make_pair(entry_name, EntryValue(entry_value)));
}
// Make this function private to avoid adding undefined data types.

View File

@ -78,7 +78,10 @@ bool MetadataDecoder::DecodeEntry(Metadata *metadata) {
if (!DecodeName(&entry_name))
return false;
uint32_t data_size = 0;
DecodeVarint(&data_size, buffer_);
if (!DecodeVarint(&data_size, buffer_))
return false;
if (data_size == 0)
return false;
std::vector<uint8_t> entry_value(data_size);
if (!buffer_->Decode(&entry_value[0], data_size))
return false;

View File

@ -148,6 +148,7 @@ void PointCloud::DeleteAttribute(int att_id) {
}
}
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
void PointCloud::DeduplicatePointIds() {
// Hashing function for a single vertex.
auto point_hash = [this](PointIndex p) {
@ -225,5 +226,6 @@ bool PointCloud::DeduplicateAttributeValues() {
}
return true;
}
#endif
} // namespace draco

View File

@ -95,6 +95,7 @@ class PointCloud {
// attribute ids of all subsequent attributes.
virtual void DeleteAttribute(int att_id);
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
// Deduplicates all attribute values (all attribute entries with the same
// value are merged into a single entry).
virtual bool DeduplicateAttributeValues();
@ -102,6 +103,7 @@ class PointCloud {
// Removes duplicate point ids (two point ids are duplicate when all of their
// attributes are mapped to the same entry ids).
virtual void DeduplicatePointIds();
#endif
// Add metadata.
void AddMetadata(std::unique_ptr<GeometryMetadata> metadata) {
@ -162,10 +164,12 @@ class PointCloud {
void set_num_points(PointIndex::ValueType num) { num_points_ = num; }
protected:
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
// Applies id mapping of deduplicated points (called by DeduplicatePointIds).
virtual void ApplyPointIdDeduplication(
const IndexTypeVector<PointIndex, PointIndex> &id_map,
const std::vector<PointIndex> &unique_point_ids);
#endif
private:
// Metadata for the point cloud.

View File

@ -61,10 +61,12 @@ void PointCloudBuilder::SetAttributeValuesForAllPoints(
std::unique_ptr<PointCloud> PointCloudBuilder::Finalize(
bool deduplicate_points) {
#ifdef DRACO_ATTRIBUTE_DEDUPLICATION_SUPPORTED
if (deduplicate_points) {
point_cloud_->DeduplicateAttributeValues();
point_cloud_->DeduplicatePointIds();
}
#endif
return std::move(point_cloud_);
}

Some files were not shown because too many files have changed in this diff Show More