mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-08-10 07:09:01 +08:00
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:
parent
8492a2b279
commit
a7c0d80a71
@ -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)
|
||||
|
@ -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)
|
||||
|
11
README.md
11
README.md
@ -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.
28
javascript/draco_decoder_gltf.js
Normal file
28
javascript/draco_decoder_gltf.js
Normal file
File diff suppressed because one or more lines are too long
BIN
javascript/draco_decoder_gltf.wasm
Normal file
BIN
javascript/draco_decoder_gltf.wasm
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -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"!==
|
||||
|
124
javascript/draco_wasm_wrapper_gltf.js
Normal file
124
javascript/draco_wasm_wrapper_gltf.js
Normal 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);
|
@ -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
@ -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": {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)));
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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))
|
||||
|
@ -30,7 +30,7 @@ class MeshPredictionSchemeGeometricNormalPredictorArea
|
||||
Base;
|
||||
|
||||
public:
|
||||
MeshPredictionSchemeGeometricNormalPredictorArea(const MeshDataT &md)
|
||||
explicit MeshPredictionSchemeGeometricNormalPredictorArea(const MeshDataT &md)
|
||||
: Base(md) {
|
||||
this->SetNormalPredictionMode(TRIANGLE_AREA);
|
||||
};
|
||||
|
@ -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) {}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {}
|
||||
|
@ -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.
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -47,7 +47,7 @@ class PredictionSchemeWrapTransformBase {
|
||||
max_correction_(0),
|
||||
min_correction_(0) {}
|
||||
|
||||
PredictionSchemeTransformType GetType() const {
|
||||
static constexpr PredictionSchemeTransformType GetType() {
|
||||
return PREDICTION_TRANSFORM_WRAP;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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_;
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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].
|
||||
|
@ -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>());
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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>());
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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()))
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#endif // defined(_MSC_VER)
|
||||
#endif // defined(_MSC_VER)
|
||||
|
||||
namespace draco {
|
||||
namespace bits {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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_
|
||||
|
@ -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>(
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user