@woosh/meep-engine 2.111.3 → 2.111.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/package.json +1 -1
  3. package/src/core/geom/3d/tetrahedra/delaunay/Cavity.d.ts +7 -7
  4. package/src/core/geom/3d/tetrahedra/delaunay/Cavity.d.ts.map +1 -1
  5. package/src/core/geom/3d/tetrahedra/delaunay/Cavity.js +45 -40
  6. package/src/core/geom/3d/tetrahedra/delaunay/compute_delaunay_tetrahedral_mesh.js +1 -1
  7. package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.d.ts +1 -2
  8. package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.d.ts.map +1 -1
  9. package/src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +6 -31
  10. package/src/core/geom/3d/tetrahedra/delaunay/grid/tetrahedral_mesh_build_from_grid.d.ts.map +1 -0
  11. package/src/core/geom/3d/tetrahedra/delaunay/{tetrahedral_mesh_build_from_grid.js → grid/tetrahedral_mesh_build_from_grid.js} +28 -10
  12. package/src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_sub_determinant.d.ts.map +1 -1
  13. package/src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_sub_determinant.js +8 -1
  14. package/src/core/geom/3d/tetrahedra/prototypeTetrahedraBuilder.js +1 -1
  15. package/src/core/geom/3d/tetrahedra/validate_tetrahedral_mesh.d.ts.map +1 -1
  16. package/src/core/geom/3d/tetrahedra/validate_tetrahedral_mesh.js +27 -0
  17. package/src/core/geom/3d/topology/struct/TopoMesh.d.ts +9 -2
  18. package/src/core/geom/3d/topology/struct/TopoMesh.d.ts.map +1 -1
  19. package/src/core/geom/3d/topology/struct/TopoMesh.js +27 -17
  20. package/src/core/geom/vec3/v3_array_immediate_add.d.ts +3 -3
  21. package/src/core/geom/vec3/v3_array_immediate_add.d.ts.map +1 -1
  22. package/src/core/geom/vec3/v3_array_immediate_add.js +2 -2
  23. package/src/engine/ecs/terrain/BufferedGeometryArraysBuilder.d.ts.map +1 -1
  24. package/src/engine/ecs/terrain/BufferedGeometryArraysBuilder.js +4 -2
  25. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.d.ts +9 -0
  26. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.d.ts.map +1 -0
  27. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.js +45 -0
  28. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_unindexed.d.ts +7 -0
  29. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_unindexed.d.ts.map +1 -0
  30. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_unindexed.js +42 -0
  31. package/src/engine/graphics/geometry/buffered/v3_array_normalize_many.d.ts +8 -0
  32. package/src/engine/graphics/geometry/buffered/v3_array_normalize_many.d.ts.map +1 -0
  33. package/src/engine/graphics/geometry/buffered/v3_array_normalize_many.js +22 -0
  34. package/src/engine/graphics/geometry/geometry_construct_triangle_normal.d.ts +2 -2
  35. package/src/engine/graphics/geometry/geometry_construct_triangle_normal.d.ts.map +1 -1
  36. package/src/engine/graphics/geometry/geometry_construct_triangle_normal.js +1 -1
  37. package/src/engine/graphics/sh3/lpv/LightProbeVolume.js +1 -1
  38. package/src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_build_from_grid.d.ts.map +0 -1
  39. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals.d.ts +0 -9
  40. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals.d.ts.map +0 -1
  41. package/src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals.js +0 -91
  42. /package/src/core/geom/3d/tetrahedra/{cube_split_to_6_tetr.png → delaunay/grid/cube_split_to_6_tetr.png} +0 -0
  43. /package/src/core/geom/3d/tetrahedra/delaunay/{tetrahedral_mesh_build_from_grid.d.ts → grid/tetrahedral_mesh_build_from_grid.d.ts} +0 -0
@@ -1 +1 @@
1
- function t(t,e){const n=t.length;if(n!==e.length)return!1;for(let i=0;i<n;i++)if(t[i]!==e[i])return!1;return!0}class e{appendDescriptionOf(t){throw new Error("Not Implemented")}appendList(t,e,n,i){throw new Error("Not Implemented")}appendText(t){throw new Error("Not Implemented")}appendValue(t){throw new Error("Not Implemented")}appendValueList(t,e,n,i){throw new Error("Not Implemented")}}class n{describeTo(t){throw new Error("Not Implemented")}}class i extends n{value;constructor(t){super(),this.value=t}describeTo(t){t.appendValue(this.value)}}class r{#t;constructor(t){this.#t=t}*[Symbol.iterator](){for(const t of this.#t)yield new i(t)}}class s extends e{appendDescriptionOf(t){return t.describeTo(this),this}#e(t){this.appendText('"'),this.appendText(t),this.appendText('"')}appendValue(t){return null==t?this.appendText("null"):void 0===t?this.appendText("undefined"):"string"==typeof t?this.#e(t):"number"==typeof t?this.appendText(function(t){return String(t)}(t)):Array.isArray(t)?this.appendValueList("[",", ","]",t):(this.appendText("<"),this.appendText(function(t){try{return String(t)}catch(t){return"VALUE@0"}}(t)),this.appendText(">")),this}appendValueList(t,e,n,i){return this.appendList(t,e,n,new r(i)),this}appendList(t,e,n,i){let r=!1;this.appendText(t);const s=i[Symbol.iterator]();for(let t=s.next();!0!==t.done;t=s.next())r&&this.appendText(e),this.appendDescriptionOf(t.value),r=!0;return this.appendText(n),this}}class o extends s{value="";appendText(t){return this.value+=t,this}}function a(t,e){if(!t)throw new Error(e||"AssertionError")}function h(t,e,n,i,r){let s,o,a;for(a=0;a<r;a++)s=e+a,o=i+a,n[o]=t[s]}a.enum=function(t,e,n="value"){for(let n in e)if(e[n]===t)return;throw new Error(`${n}(=${t}) is not a valid enumerable value, valid values are: [${Object.values(e).join(", ")}]`)},a.notEqual=function(t,e,n){a(t!==e,n)},a.notOk=function(t,e){a(!t,e)},a.equal=function(t,e,n){if(t!==e){const i=`${t} !== ${e}`;throw new Error(void 0!==n&&""!==n?`${n}. ${i}`:i)}},a.logicalyEqual=function(t,e,n){},a.ok=a,a.greaterThan=function(t,e,n){if(!(t>e)){let i="";throw void 0!==n&&(i+=n+". "),i+=`Expected ${t} > ${e}.`,new Error(i)}},a.greaterThanOrEqual=function(t,e,n){if(!(t>=e)){let i="";throw void 0!==n&&(i+=n+". "),i+=`Expected ${t} >= ${e}.`,new Error(i)}},a.lessThan=function(t,e,n){if(!(t<e)){let i="";throw void 0!==n&&(i+=n+". "),i+=`Expected ${t} < ${e}.`,new Error(i)}},a.lessThanOrEqual=function(t,e,n){if(!(t<=e)){let i="";throw void 0!==n&&(i+=n+". "),i+=`Expected ${t} <= ${e}.`,new Error(i)}},a.typeOf=function(t,e,n="value"){const i=typeof t;if(i!==e)throw new Error(`expected ${n} to be ${e}, instead was '${i}'(=${t})`)},a.arrayHas=function(t,e,n="Array does not contain the item"){},a.arrayHasNo=function(t,e,n="Array contains the item"){},a.arrayEqual=function(e,n,i="Arrays are not equal"){if(!t(e,n))throw new Error(i)},a.isInstanceOf=function(t,e,n="value",i=e.name){},a.isNumber=function(t,e="value"){const n=typeof t;if("number"!==n)throw new Error(`expected ${e} to be a number, instead was '${n}'(=${t})`)},a.isString=function(t,e="value"){const n=typeof t;if("string"!==n)throw new Error(`expected ${e} to be a string, instead was '${n}'(=${t})`)},a.isBoolean=function(t,e="value"){const n=typeof t;if("boolean"!==n)throw new Error(`expected ${e} to be a boolean, instead was '${n}'(=${t})`)},a.isFunction=function(t,e="value"){const n=typeof t;if("function"!==n)throw new Error(`expected ${e} to be a function, instead was '${n}'(=${t})`)},a.isObject=function(t,e="value"){const n=typeof t;if("object"!==n)throw new Error(`expected ${e} to be an object, instead was '${n}'(=${t})`)},a.isInteger=function(t,e="value"){if(!Number.isInteger(t))throw new Error(`${e} must be an integer, instead was ${t}`)},a.isNonNegativeInteger=function(t,e="value"){if(t<0)throw new Error(`${e} must be >= 0, instead was ${t}`)},a.isArray=function(t,e="value"){if(!Array.isArray(t))throw new Error(`expected ${e} to be an array, instead was something else (typeof ='${typeof t}')`)},a.isArrayLike=function(t,e="value"){if(!(Array.isArray(t)||(n=t,n instanceof Int8Array||n instanceof Uint8Array||n instanceof Uint8ClampedArray||n instanceof Int16Array||n instanceof Uint16Array||n instanceof Int32Array||n instanceof Uint32Array||n instanceof Float32Array||n instanceof Float64Array)))throw new Error(`expected ${e} to be an array-like structure, instead was something else (typeof ='${typeof t}')`);var n},a.defined=function(t,e="value"){if(void 0===t)throw new Error(`${e} is undefined`)},a.isNull=function(t,e){if(null!==t)throw new Error(`${e} is NOT null`)},a.notNull=function(t,e="value"){if(null===t)throw new Error(`${e} is null`)},a.notNaN=function(t,e="value"){if(Number.isNaN(t))throw new Error(`${e} must be a valid number, instead was NaN`)},a.isFiniteNumber=function(t,e="value"){if(!Number.isFinite(t))throw new Error(`${e} must be a finite number, instead was ${t}`)},a.that=function(t,e,n){if(n.matches(t))return;const i=new o;throw i.appendText(`Expected ${e} to be `),n.describeTo(i),i.appendText(" instead "),n.describeMismatch(t,i),new Error(i.value)};const c=new Uint32Array(781250);function d(t,e){return t<e?e:t}function u(t,e){return t<e?t:e}function l(t,e,n,i,r,s){const o=n[i+0],a=n[i+1],h=n[i+2],c=n[i+3],l=n[i+4],f=n[i+5],g=r[s+0],_=r[s+1],p=r[s+2],y=r[s+3],m=r[s+4],w=r[s+5],v=u(o,g),x=u(a,_),b=u(h,p),A=d(c,y),E=d(l,m),$=d(f,w);t[e+0]=v,t[e+1]=x,t[e+2]=b,t[e+3]=A,t[e+4]=E,t[e+5]=$}function f(t,e,n,i,r,s,o,a){t[e]=n,t[e+1]=i,t[e+2]=r,t[e+3]=s,t[e+4]=o,t[e+5]=a}function g(t,e,n,i,r,s){const o=i-t,a=s-n;return(r-e)*(o+a)+a*o}function _(t){let e=t;return e=50331903&(e|e<<16),e=50393103&(e|e<<8),e=51130563&(e|e<<4),e=153391689&(e|e<<2),e}function p(t,e,n){let i=t;return i<e&&(i=e),i<n&&(i=n),i}function y(t,e,n){let i=t;return i>e&&(i=e),i>n&&(i=n),i}function m(t,e,n){const i=t[n],r=t[n+1],s=t[n+2];f(t,e,i,r,s,i,r,s)}function w(t,e,n){const i=t[e],r=t[e+1],s=t[e+2];return function(t,e,n,i){const r=i[0],s=i[1],o=i[2],a=1023*(t-r)/(i[3]-r),h=1023*(e-s)/(i[4]-s),c=1023*(n-o)/(i[5]-o);return function(t,e,n){return _(t)|_(e)<<1|_(n)<<2}(Math.round(a),Math.round(h),Math.round(c))}(.5*(i+t[e+3]),.5*(r+t[e+4]),.5*(s+t[e+5]),n)}c.pointer=0;const v=c;class x{__data_buffer;__data_float32;__data_uint32;__node_count_binary=0;__node_count_leaf=0;constructor(){this.data=new ArrayBuffer(320)}estimateByteSize(){return this.data.byteLength+248}getTotalBoxCount(){return this.__node_count_binary+this.__node_count_leaf}get binary_node_count(){return this.__node_count_binary}get leaf_node_count(){return this.__node_count_leaf}getLeafBlockAddress(){return 6*this.__node_count_binary}get float32(){return this.__data_float32}get uint32(){return this.__data_uint32}set data(t){this.__data_buffer=t,this.__data_float32=new Float32Array(this.__data_buffer),this.__data_uint32=new Uint32Array(this.__data_buffer)}get data(){return this.__data_buffer}getNodeAddress(t){const e=this.__node_count_binary,n=t-e;return n<0?6*t:6*e+7*n}initialize_structure(){const t=4*(6*this.__node_count_binary+7*this.__node_count_leaf);this.__data_buffer.byteLength<t&&(this.data=new ArrayBuffer(t))}setLeafCount(t){this.__node_count_leaf=t;const e=function(t){let e=t-1;return e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,e|=e>>16,e++,e}(t);this.__node_count_binary=t<=1?e:e-1}getLeafAddress(t){return 7*t+6*this.__node_count_binary}setLeafData(t,e,n,i,r,s,o,a){const h=this.getLeafAddress(t);f(this.__data_float32,h,n,i,r,s,o,a),this.__data_uint32[h+6]=e}readBounds(t,e,n){h(this.__data_float32,t,e,n,6)}readLeafPayload(t){const e=this.getLeafBlockAddress()+7*t+6;return this.__data_uint32[e]}compute_total_surface_area(){let t=0;const e=new Float32Array(6);for(let n=0;n<this.getTotalBoxCount();n++){let i;i=n<this.__node_count_binary?6*n:7*(n-this.__node_count_binary)+this.getLeafBlockAddress(),this.readBounds(i,e,0),t+=g(e[0],e[1],e[2],e[3],e[4],e[5])}return t}__compute_bounds_area_of_3_boxes(t,e,n){const i=this.__data_float32;return g(y(i[t+0],i[e+0],i[n+0]),y(i[t+1],i[e+1],i[n+1]),y(i[t+2],i[e+2],i[n+2]),p(i[t+3],i[e+3],i[n+3]),p(i[t+4],i[e+4],i[n+4]),p(i[t+5],i[e+5],i[n+5]))}__fitness_function_should_swap_leaves_sah(t,e){const n=d(t-1,0),i=u(t+1,this.__node_count_leaf-1),r=this.getLeafBlockAddress(),s=7*t+r,o=7*n+r,a=7*i+r,h=7*e+r,c=7*d(e-1,0)+r,l=7*u(e+1,this.__node_count_leaf-1)+r;return this.__compute_bounds_area_of_3_boxes(o,s,a)+this.__compute_bounds_area_of_3_boxes(c,h,l)-(this.__compute_bounds_area_of_3_boxes(o,h,a)+this.__compute_bounds_area_of_3_boxes(c,s,l))}sort_bubble_sah(){const t=this.__node_count_leaf;for(let e=0;e<t;e++)for(let n=e+1;n<t;n++)this.__fitness_function_should_swap_leaves_sah(e,n)>0&&this.__swap_leaves(e,n)}sort_morton(t){const e=6*this.__node_count_binary;if(this.__node_count_leaf<2)return;let n,i,r=2;v[0]=0,v[1]=this.__node_count_leaf-1;const s=this.__data_float32;for(;r>0;){r-=2;const o=v[r+1],a=v[r];n=a,i=o;const h=w(s,7*(a+o>>1)+e,t);for(;n<=i;){for(;w(s,7*n+e,t)<h;)n++;for(;w(s,7*i+e,t)>h;)i--;n<=i&&(n!==i&&this.__swap_leaves(n,i),n++,i--)}a<i&&(v[r++]=a,v[r++]=i),n<o&&(v[r++]=n,v[r++]=o)}}__swap_leaves(t,e){const n=this.getLeafBlockAddress(),i=7*t+n,r=7*e+n;!function(t,e,n,i,r){for(let r=0;r<7;r++){const s=e+r,o=i+r,a=n[o];n[o]=t[s],t[s]=a}}(this.__data_float32,i,this.__data_float32,r)}build(){const t=this.__node_count_binary,e=6*t;let n,i,r,s,o=Math.floor(Math.log(t)/Math.log(2));r=Math.pow(2,o),i=6*(r-1);const a=this.__node_count_leaf,c=this.__data_float32;for(n=0;n<r;n++){const t=n<<1,r=t+1,s=e+7*t;r<a?l(c,i,c,s,c,e+7*r):t<a?h(c,s,c,i,6):m(this.__data_float32,i,i-6),i+=6}for(o--;o>=0;o--)for(r=1<<o,s=r-1,n=0;n<r;n++){const t=6*(1+(s<<1));l(c,6*s,c,t,c,t+6),s++}}}function b(t,e,n,i,r,s){const o=t.getLeafAddress(e);!function(t,e,n,i,r,s){const o=3*i,a=3*r,h=3*s,c=n[o],d=n[o+1],u=n[o+2],l=n[a],f=n[a+1],g=n[a+2],_=n[h],m=n[h+1],w=n[h+2];t[e]=y(c,l,_),t[e+1]=y(d,f,m),t[e+2]=y(u,g,w),t[e+3]=p(c,l,_),t[e+4]=p(d,f,m),t[e+5]=p(u,g,w)}(t.__data_float32,o,n,i,r,s),t.__data_uint32[o+6]=e}const A=[],E=[],$="undefined"!=typeof Uint8Array?Uint8Array:Array,S="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(let t=0,e=64;t<e;++t)A[t]=S[t],E[S.charCodeAt(t)]=t;function U(t,e,n){const i=[];for(let s=e;s<n;s+=3){const e=(t[s]<<16&16711680)+(t[s+1]<<8&65280)+(255&t[s+2]);i.push(A[(r=e)>>18&63]+A[r>>12&63]+A[r>>6&63]+A[63&r])}var r;return i.join("")}E["-".charCodeAt(0)]=62,E["_".charCodeAt(0)]=63;class F{static encode(t){return function(t){let e;const n=t.length,i=n%3,r=[],s=16383,o=n-i;for(let e=0;e<o;e+=s){const n=U(t,e,e+s>o?o:e+s);r.push(n)}return 1===i?(e=t[n-1],r.push(A[e>>2]+A[e<<4&63]+"==")):2===i&&(e=(t[n-2]<<8)+t[n-1],r.push(A[e>>10]+A[e>>4&63]+A[e<<2&63]+"=")),r.join("")}(new Uint8Array(t))}static decode(t){return function(t){var e,n,i=function(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var n=t.indexOf("=");return-1===n&&(n=e),[n,n===e?0:4-n%4]}(t),r=i[0],s=i[1],o=new $(function(t,e,n){return 3*(e+n)/4-n}(0,r,s)),a=0,h=s>0?r-4:r;for(n=0;n<h;n+=4)e=E[t.charCodeAt(n)]<<18|E[t.charCodeAt(n+1)]<<12|E[t.charCodeAt(n+2)]<<6|E[t.charCodeAt(n+3)],o[a++]=e>>16&255,o[a++]=e>>8&255,o[a++]=255&e;return 2===s&&(e=E[t.charCodeAt(n)]<<2|E[t.charCodeAt(n+1)]>>4,o[a++]=255&e),1===s&&(e=E[t.charCodeAt(n)]<<10|E[t.charCodeAt(n+1)]<<4|E[t.charCodeAt(n+2)]>>2,o[a++]=e>>8&255,o[a++]=255&e),o}(t).buffer}}const z="uint8",C="uint16",V="uint32",B="int8",q="int16",L="int32",M="float32",T="float64",I={[z]:Uint8Array,[C]:Uint16Array,[V]:Uint32Array,[B]:Int8Array,[q]:Int16Array,[L]:Int32Array,float16:Uint16Array,[M]:Float32Array,[T]:Float64Array};function N(t){switch(Object.getPrototypeOf(t).constructor){case Uint8Array:case Uint8ClampedArray:return z;case Uint16Array:return C;case Uint32Array:return V;case Int8Array:return B;case Int16Array:return q;case Int32Array:return L;case Float32Array:return M;case Float64Array:return T;default:throw new Error("unsupported constructor type")}}function O(t,e,n){return t<e?e:t>n?n:t}function k(t,e,n){return(e-t)*n+t}function j(t,e,n,i,r){return.5*(i-e+(2*e-5*n+4*i-r+(3*(n-i)+r-e)*t)*t)*t+n}class D{constructor(t=[],e=1,n=0,i=0){if(!Number.isInteger(e)||e<0)throw new Error(`itemSize must be a non-negative integer, instead was ${e}`);if(!Number.isInteger(n)||n<0)throw new Error(`width must be a non-negative integer, instead was ${n}`);if(!Number.isInteger(i)||n<0)throw new Error(`height must be a non-negative integer, instead was ${i}`);if(void 0===t)throw new Error("data was undefined");if(t.length<n*i*e)throw new Error(`Buffer underflow, data.length(=${t.length}) is too small. Expected at least ${n*i*e}`);this.width=n,this.height=i,this.itemSize=e,this.data=t,this.version=0}get(t,e,n){throw new Error("Deprecated method, use sampleBilinear instead")}sampleCatmullRomUV(t,e,n){const i=this.itemSize;for(let r=0;r<i;r++)n[r]=this.sampleChannelCatmullRomUV(t,e,r)}sampleChannelCatmullRomUV(t,e,n){const i=t*this.width-.5,r=e*this.height-.5;return this.sampleChannelCatmullRom(i,r,n)}sampleChannelCatmullRom(t,e,n){const i=Math.floor(t),r=Math.floor(e),s=t-i,o=e-r,a=s*(s*(1-.5*s)-.5),h=o*(o*(1-.5*o)-.5),c=s*(.5+s*(2-1.5*s)),d=o*(.5+o*(2-1.5*o)),u=s*s*(.5*s-.5),l=o*o*(.5*o-.5),f=1+s*s*(1.5*s-2.5)+c,g=1+o*o*(1.5*o-2.5)+d,_=i-1,p=r-1,y=i+2,m=r+2,w=i+c/f,v=r+d/g;let x=0;return x+=this.sampleChannelBilinear(_,p,n)*a*h,x+=this.sampleChannelBilinear(w,p,n)*f*h,x+=this.sampleChannelBilinear(y,p,n)*u*h,x+=this.sampleChannelBilinear(_,v,n)*a*g,x+=this.sampleChannelBilinear(w,v,n)*f*g,x+=this.sampleChannelBilinear(y,v,n)*u*g,x+=this.sampleChannelBilinear(_,m,n)*a*l,x+=this.sampleChannelBilinear(w,m,n)*f*l,x+=this.sampleChannelBilinear(y,m,n)*u*l,x}sampleBicubicUV(t,e,n){const i=this.itemSize;for(let r=0;r<i;r++)n[r]=this.sampleChannelBicubicUV(t,e,r)}sampleBicubic(t,e,n,i){const r=this.itemSize;for(let s=0;s<r;s++)n[s+i]=this.sampleChannelBicubic(t,e,s)}sampleChannelBicubicUV(t,e,n){const i=t*this.width,r=e*this.height;return this.sampleChannelBicubic(i-.5,r-.5,n)}sampleChannelBicubic(t,e,n){const i=this.itemSize,r=this.width,s=this.height,o=this.data,a=r*i,h=r-1,c=s-1,l=O(t,0,h),f=O(e,0,c),g=0|l,_=0|f,p=l-g,y=f-_,m=d(0,g-1),w=d(0,_-1),v=u(h,g+1),x=u(c,_+1),b=u(h,v+1),A=w*a+n,E=_*a+n,$=x*a+n,S=u(c,x+1)*a+n,U=m*i,F=g*i,z=v*i,C=b*i,V=o[A+U],B=o[A+F],q=o[A+z],L=o[A+C],M=o[E+U],T=o[E+F],I=o[E+z],N=o[E+C],k=o[$+U],D=o[$+F],R=o[$+z],J=o[$+C],P=o[S+U],H=o[S+F],W=o[S+z],G=o[S+C],Y=j(p,V,B,q,L),K=j(p,M,T,I,N),Q=j(p,k,D,R,J),X=j(p,P,H,W,G);return j(y,Y,K,Q,X)}sampleBilinearUV(t,e,n,i=0){const r=this.itemSize;for(let s=0;s<r;s++)n[s+i]=this.sampleChannelBilinearUV(t,e,s)}sampleBilinear(t,e,n,i=0){const r=this.itemSize;for(let s=0;s<r;s++)n[s+i]=this.sampleChannelBilinear(t,e,s)}sampleChannelBilinearUV(t,e,n){const i=t*this.width-.5,r=e*this.height-.5;return this.sampleChannelBilinear(i,r,n)}sampleChannelBilinear(t,e,n){const i=this.itemSize,r=this.width,s=r*i,o=this.height-1,a=O(t,0,r-1),h=O(e,0,o),c=a>>>0,d=h>>>0,u=d*s,l=c*i+n,f=u+l;let g,_;g=a===c?c:c+1,_=h===d?d:d+1;const p=this.data,y=p[f];if(c===g&&d===_)return y;const m=a-c,w=h-d,v=g*i+n,x=_*s,b=x+l,A=x+v,E=p[u+v],$=p[b],S=p[A],U=k(y,E,m),F=k($,S,m);return k(U,F,w)}sampleNearestUV(t,e,n){const i=this.width,r=this.height,s=Math.round(t*i-.5),o=Math.round(e*r-.5);this.read(O(s,0,i-1),O(o,0,r-1),n)}readChannel(t,e,n){const i=(e*this.width+t)*this.itemSize+n;return this.data[i]}read(t,e,n){const i=this.width,r=this.itemSize,s=(e*i+t)*r;for(let t=0;t<r;t++)n[t]=this.data[s+t]}write(t,e,n){const i=this.width,r=this.itemSize,s=(e*i+t)*r;for(let t=0;t<r;t++)this.data[s+t]=n[t]}sample(t,e,n){const i=[];return this.sampleBilinear(t*(this.width-1),e*(this.height-1),i,0),n.readFromArray(i),i[0]}point2index(t,e){return t+e*this.width}index2point(t,e){const n=this.width,i=t%n,r=t/n|0;e.set(i,r)}copy(t,e,n,i,r,s,o){const a=Math.min(s,t.width-e,this.width-i),h=Math.min(o,t.height-n,this.height-r),c=this.itemSize,d=t.itemSize,u=Math.min(c,d),l=c*this.width,f=d*t.width,g=t.data,_=this.data;let p,y,m;for(y=0;y<h;y++){const t=(y+r)*l,s=(y+n)*f;for(p=0;p<a;p++){const n=t+(p+i)*c,r=s+(p+e)*d;for(m=0;m<u;m++)_[n+m]=g[r+m]}}this.version++}zeroFill(t,e,n,i){const r=O(t,0,this.width),s=O(e,0,this.height),o=O(t+n,0,this.width),a=O(e+i,0,this.height),h=this.data,c=this.itemSize,d=c*this.width,u=r*c,l=o*c;let f;for(f=s;f<a;f++){const t=f*d;h.fill(0,t+u,t+l)}this.version++}channelFill(t,e){const n=this.itemSize,i=this.data,r=i.length;for(let s=t;s<r;s+=n)i[s]=e;this.version++}fill(t,e,n,i,r){const s=this.width,o=this.height,a=O(t,0,s),h=O(e,0,o),c=O(t+n,0,s),d=O(e+i,0,o),u=this.data,l=this.itemSize,f=l*s;let g,_,p;for(g=h;g<d;g++){const t=g*f;for(_=a;_<c;_++){const e=t+_*l;for(p=0;p<l;p++)u[e+p]=r[p]}}this.version++}writeChannel(t,e,n,i){const r=(e*this.width+t)*this.itemSize+n;this.data[r]=i,this.version++}set(t,e,n){const i=this.data,r=this.itemSize,s=r*this.width*e+t*r;for(let t=0;t<r;t++)i[s+t]=n[t];this.version++}traverseCircle(t,e,n,i){let r,s;const o=0|t,a=0|e,h=n*n,c=Math.ceil(n);for(s=-c;s<=c;s++){const t=s*s;for(r=-c;r<=c;r++)r*r+t<=h&&i(o+r,a+s,this)}}resize(t,e,n=!0){const i=this.width,r=this.height;if(i===t&&r===e)return;const s=this.itemSize,o=t*e*s,a=this.data,h=new(function(t){if(t instanceof Int8Array)return Int8Array;if(t instanceof Int16Array)return Int16Array;if(t instanceof Int32Array)return Int32Array;if(t instanceof Uint8Array)return Uint8Array;if(t instanceof Uint8ClampedArray)return Uint8ClampedArray;if(t instanceof Uint16Array)return Uint16Array;if(t instanceof Uint32Array)return Uint32Array;if(t instanceof Float32Array)return Float32Array;if(t instanceof Float64Array)return Float64Array;if(Array.isArray(t))return Array;throw new TypeError("Unsupported array type")}(a))(o);if(n)if(t===i)h.set(a.subarray(0,Math.min(a.length,o)));else{const n=u(e,r),o=u(t,i);for(let e=0;e<n;e++)for(let n=0;n<o;n++){const r=(e*t+n)*s,o=(e*i+n)*s;for(let t=0;t<s;t++)h[r+t]=a[o+t]}}this.width=t,this.height=e,this.data=h,this.version++}computeByteSize(){let t;return t=Array.isArray(this.data)?8*this.data.length:this.data.buffer.byteLength,t+280}equals(e){return this.width===e.width&&this.height===e.height&&this.itemSize===e.itemSize&&function(e,n){if(e===n)return!0;const i=e.length;if(i!==n.length)return!1;if(0===i)return!0;if(i<128)return t(e,n);const r=e.byteLength;if(r!==n.byteLength)return!1;const s=e.constructor;if(s!==n.constructor)return!1;const o=e.buffer,a=n.buffer;if(o===a&&e.byteOffset===n.byteOffset)return!0;let h=e,c=n;const d=s.BYTES_PER_ELEMENT;return d<4&&r%4==0?(h=new Uint32Array(o,e.byteOffset,r/4),c=new Uint32Array(a,n.byteOffset,r/4)):d<2&&r%2==0&&(h=new Uint16Array(o,e.byteOffset,r/2),c=new Uint16Array(a,n.byteOffset,r/2)),t(h,c)}(this.data,e.data)}hash(){let t=((65535&this.width)<<16|65535&this.height)^this.itemSize;const e=this.data.length,n=Math.max(1,Math.ceil(e/509));return t^=function(t,e,n,i){let r=n;for(let e=0;e<n;e+=i)r=(r<<5)-r+(t[e]>>>0);return r>>>0}(this.data,0,e,n),t}clone(){let t;return t=Array.isArray(this.data)?this.data.slice():new(0,this.data.constructor)(this.data),new D(t,this.itemSize,this.width,this.height)}toJSON(){const t=F.encode(this.data.buffer);return{height:this.height,width:this.width,itemSize:this.itemSize,type:N(this.data),data:t}}fromJSON({height:t,width:e,itemSize:n,type:i,data:r}){const s=function(t){const e=I[t];if(void 0===e)throw new Error(`Unsupported data type '${t}'`);return e}(i);if("string"==typeof r){const t=F.decode(r);this.data=new s(t)}else{if(!Array.isArray(r))throw new Error("Unsupported data format");this.data=new s(r)}this.height=t,this.width=e,this.itemSize=n}static uint8clamped(t,e,n){const i=new Uint8ClampedArray(e*n*t);return new D(i,t,e,n)}static uint8(t,e,n){const i=new Uint8Array(e*n*t);return new D(i,t,e,n)}static uint16(t,e,n){const i=new Uint16Array(e*n*t);return new D(i,t,e,n)}static uint32(t,e,n){const i=new Uint32Array(e*n*t);return new D(i,t,e,n)}static int8(t,e,n){const i=new Int8Array(e*n*t);return new D(i,t,e,n)}static int16(t,e,n){const i=new Int16Array(e*n*t);return new D(i,t,e,n)}static int32(t,e,n){const i=new Int32Array(e*n*t);return new D(i,t,e,n)}static float32(t,e,n){const i=new Float32Array(e*n*t);return new D(i,t,e,n)}static float64(t,e,n){const i=new Float64Array(e*n*t);return new D(i,t,e,n)}}function R(t,e,n){return Math.sqrt(t*t+e*e+n*n)}function J(t,e,n,i){const r=n[i],s=n[i+1],o=n[i+2],a=1/R(r,s,o);t[e]=r*a,t[e+1]=s*a,t[e+2]=o*a}D.prototype.isSampler2D=!0,D.typeName="Sampler2D";const P={build:function(t,e,n,i,r,s){const o=n.x*s,a=n.y*s,h=o-1,c=a-1;let d=0,u=0;const l=o*a,f=new Float32Array(3*l),g=new Float32Array(3*l),_=new Float32Array(2*l);let p,y;const m=n.y/r.y/c,w=n.x/r.x/h,v=e.y/r.y,x=e.x/r.x,b=r.x*i.x,A=r.y*i.y;let E,$,S;for(p=0;p<a;p++){const e=p*m+v;for(S=e*A,y=0;y<o;y++){const n=y*w+x;E=n*b,$=t.sampleChannelBicubicUV(n,e,0),f[d]=E,f[d+1]=$,f[d+2]=S,_[u]=n,_[u+1]=e,d+=3,u+=2}}d=0;const U=new(f.length/3>65535?Uint32Array:Uint16Array)(h*c*6);for(p=0;p<c;p++)for(y=0;y<h;y++){const t=y+o*p,e=y+o*(p+1),n=y+1+o*(p+1),i=y+1+o*p;U[d]=t,U[d+1]=e,U[d+2]=i,U[d+3]=e,U[d+4]=n,U[d+5]=i,d+=6}return function(t,e,n){let i,r,s,o,a,h,c,d,u,l,f,g,_,p,y,m,w,v,x,b,A,E=0;const $=n.length;for(;E<$;E+=3)i=3*n[E],r=3*n[E+1],s=3*n[E+2],o=t[i],a=t[i+1],h=t[i+2],c=t[r],d=t[r+1],u=t[r+2],l=t[s],f=t[s+1],g=t[s+2],_=l-c,p=f-d,y=g-u,m=o-c,w=a-d,v=h-u,x=p*v-y*w,b=y*m-_*v,A=_*w-p*m,e[i]+=x,e[i+1]+=b,e[i+2]+=A,e[r]+=x,e[r+1]+=b,e[r+2]+=A,e[s]+=x,e[s+1]+=b,e[s+2]+=A;!function(t){const e=t.length;for(let n=0;n<e;n+=3)J(t,n,t,n)}(e)}(f,g,U),{indices:U,vertices:f,normals:g,uvs:_}}};function H(t,e,n=0,i=t.length){const r=n+i;for(let i=n;i<r;i++)if(t[i]===e)return t.splice(i,1),!0;return!1}function W(t,e){return-1===t.indexOf(e)&&(t.push(e),!0)}function G(t,e){return t.v0===e?t.v1:t.v1===e?t.v0:null}let Y=0;class K{constructor(){this.index=Y++,this.v0=null,this.v1=null,this.faces=[],this.lengthSqr=-1}get byteSize(){return 128+8*this.faces.length+10}getVertexByIndex(t){if(0===t)return this.v0;if(1===t)return this.v1;throw new Error("Index out of bounds")}copy(t){this.v0=t.v0,this.v1=t.v1,this.lengthSqr=t.lengthSqr,this.faces=t.faces.slice()}clone(){const t=new K;return t.copy(this),t}validate(t){let e=!0;const n=this.faces,i=n.length;for(let r=0;r<i;r++)n[r].containsEdge(this)||(t(`Missing back-link from face[${r}]`),e=!1);return this.v0.containsEdge(this)||(t("Missing back-link from vertex v0"),e=!1),this.v1.containsEdge(this)||(t("Missing back-link from vertex v1"),e=!1),e}isLinked(){return this.v0.containsEdge(this)}unlink(){const t=this.v0,e=this.v1;t.removeEdge(this),t!==e&&e.removeEdge(this);const n=this.faces,i=n.length;for(let t=0;t<i;t++)n[t].removeEdge(this)}isDegenerateEdge(){return this.v0===this.v1}isTopologyBorder(){return 1===this.faces.length}get length(){return this.lengthSqr<0&&this.computeSquaredLength(),Math.sqrt(this.lengthSqr)}computeSquaredLength(){const t=this.v0,e=this.v1,n=t.x,i=t.y,r=t.z,s=n-e.x,o=i-e.y,a=r-e.z;this.lengthSqr=s*s+o*o+a*a}replaceVertex(t,e){t===this.v0&&(this.v0=e),t===this.v1&&(this.v1=e)}merge(t){const e=t.faces,n=this.faces,i=e.length;for(let r=0;r<i;r++){const i=e[r];i.removeEdge(t),-1===n.indexOf(i)&&(n.push(i),i.addUniqueEdge(this))}t.v0.removeEdge(t),t.v1.removeEdge(t)}containsFace(t){return-1!==this.faces.indexOf(t)}addFace(t){this.faces.push(t)}addUniqueFace(t){W(this.faces,t)}removeFace(t){H(this.faces,t)}getOtherVertex(t){return G(this,t)}containsVertex(t){return e=t,this.v0===e||this.v1===e;var e}containsBothVertices(t,e){return function(t,e,n){const i=t.v0,r=t.v1;return!(i!==e&&i!==n||r!==e&&r!==n)}(this,t,e)}containsSameVerticesAs(t){return this.containsBothVertices(t.v0,t.v1)}}function Q(t,e,n){const i=t.length;for(let r=0;r<i;r++)t[r]===e&&(t[r]=n)}K.prototype.isTopoEdge=!0;var X,Z="undefined"!=typeof Float32Array?Float32Array:Array;function tt(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t}Math.hypot||(Math.hypot=function(){for(var t=0,e=arguments.length;e--;)t+=arguments[e]*arguments[e];return Math.sqrt(t)}),X=new Z(3),Z!=Float32Array&&(X[0]=0,X[1]=0,X[2]=0);let et=0;class nt{constructor(){this.index=et++,this.vertices=[],this.edges=[],this.normal=[0,0,0]}get byteSize(){return 100+8*this.vertices.length+10+8*this.edges.length+10+24+10}copy(t){this.index=t.index,this.vertices=t.vertices.slice(),this.edges=t.edges.slice(),tt(this.normal,t.normal)}clone(){const t=new nt;return t.copy(this),t}validate(t){let e=!0;const n=this.vertices,i=n.length;3!==i&&(t(`Expected number of vertices is 3, instead got ${i}`),e=!1);for(let r=0;r<i;r++)n[r].containsFace(this)||(t(`Missing back-link from vertex[${r}]`),e=!1);const r=this.edges,s=r.length;3!==s&&(t(`Expected number of edges is 3, instead got ${s}`),e=!1);for(let n=0;n<s;n++)r[n].containsFace(this)||(t(`Missing back-link from edge[${n}]`),e=!1);return e}isLinked(){return this.vertices[0].containsFace(this)}replaceEdge(t,e){Q(this.edges,t,e)}replaceVertex(t,e){Q(this.vertices,t,e)}isDegenerateTopology(){const t=this.vertices,e=t[0],n=t[1],i=t[2];return e===n||e===i||n===i}unlink(){const t=this.vertices,e=t.length;for(let n=0;n<e;n++)t[n].removeFace(this);const n=this.edges,i=n.length;for(let t=0;t<i;t++)n[t].removeFace(this)}addEdge(t){this.edges.push(t)}addUniqueEdge(t){return W(this.edges,t)}removeEdge(t){H(this.edges,t)}containsEdge(t){return-1!==this.edges.indexOf(t)}computeNormal(){const t=this.vertices,e=t[0],n=t[1],i=t[2];!function(t,e,n,i){!function(t,e,n,i,r,s,o,a,h,c,d){const u=h-s,l=c-o,f=d-a,g=n-s,_=i-o,p=r-a,y=l*p-f*_,m=f*g-u*p,w=u*_-l*g,v=function(t,e,n){return t*t+e*e+n*n}(y,m,w);if(0===v)return t[0]=0,t[1]=1,void(t[2]=0);const x=1/Math.sqrt(v),b=y*x,A=m*x,E=w*x;t[0]=b,t[1]=A,t[2]=E}(t,0,e[0],e[1],e[2],n[0],n[1],n[2],i[0],i[1],i[2])}(this.normal,e,n,i)}setVertexAt(t,e){this.vertices[t]=e}containsVertex(t){return-1!==this.vertices.indexOf(t)}getEdgeNeighbours(t,e){let n=0;const i=this.edges,r=i.length;for(let s=0;s<r;s++){const r=i[s].faces,o=r.length;for(let i=0;i<o;i++){const s=r[i];s!==this&&(t[e+n]=s,n++)}}return n}}nt.prototype.isTopoFace=!0;class it{constructor(){this.index=0,this.edges=[],this.faces=[],this.x=0,this.y=0,this.z=0}get 0(){return this.x}get 1(){return this.y}get 2(){return this.z}get byteSize(){return 112+8*this.edges.length+10+8*this.faces.length+10}copy(t){this.x=t.x,this.y=t.y,this.z=t.z,this.index=t.index,this.faces=t.faces.slice(),this.edges=t.edges.slice()}clone(){const t=new it;return t.copy(this),t}validate(t){let e=!0;const n=this.faces,i=n.length;for(let r=0;r<i;r++)n[r].containsVertex(this)||(t(`Missing back-link from face[${r}]`),e=!1);const r=this.edges,s=r.length;for(let n=0;n<s;n++)r[n].containsVertex(this)||(t(`Missing back-link from edge[${n}]`),e=!1);return e}distanceTo(t){return e=this.x,n=this.y,i=this.z,R(t.x-e,t.y-n,t.z-i);var e,n,i}addFace(t){this.faces.push(t)}addUniqueFace(t){return W(this.faces,t)}containsFace(t){return-1!==this.faces.indexOf(t)}removeFace(t){H(this.faces,t)}addEdge(t){this.edges.push(t)}addUniqueEdge(t){return W(this.edges,t)}replaceEdge(t,e){const n=this.edges,i=n.indexOf(t);n[i]=e}containsEdge(t){return-1!==this.edges.indexOf(t)}removeEdge(t){return H(this.edges,t)}replaceAnotherVertex(t){const e=t.faces,n=e.length;let i=0;for(;i<n;i++){const n=e[i];n.replaceVertex(t,this),this.addUniqueFace(n)}const r=t.edges,s=r.length;for(i=0;i<s;i++){const e=r[i];e.replaceVertex(t,this),this.addUniqueEdge(e)}}computeNeighbourVertices(t,e){let n=0;const i=this.edges,r=i.length;for(let s=0;s<r;s++){const r=i[s].getOtherVertex(this);t[e+n]=r,n++}return n}}function rt(t,e=","){return t.toString().replace(/\B(?=(\d{3})+(?!\d))/g,e)}it.prototype.isTopoVertex=!0;class st{constructor(){this.vertices=[],this.__edges=new Set,this.__faces=new Set}get byteSize(){let t=0;for(let e=0;e<this.vertices.length;e++)t+=this.vertices[e].byteSize;for(const e of this.__edges)t+=e.byteSize;for(const e of this.__faces)t+=e.byteSize;return t}getEdges(){return this.__edges}getFaces(){return this.__faces}getFaceByIndex(t){for(const e of this.__faces)if(e.index===t)return e}validate(t){let e=!0,n="",i=0;function r(r){t(`${n}[${i}]: ${r}`),e=!1}n="Edge",i=0;const s=this.getEdges();for(let t of s){t.validate(r),this.containsVertex(t.v0)||r("Link to off-mesh vertex v0"),this.containsVertex(t.v1)||r("Link to off-mesh vertex v1");const e=t.faces,n=e.length;for(let t=0;t<n;t++){const n=e[t];this.containsFace(n)||r(`Link to off-mesh face[${t}]`)}i++}const o=this.getFaces();n="Face",i=0;for(let t of o){t.validate(r);const e=t.edges,n=e.length;for(let t=0;t<n;t++){const n=e[t];this.containsEdge(n)||r(`Link to off-mesh edge[${t}]`)}const s=t.vertices,o=s.length;for(let t=0;t<o;t++){const e=s[t];this.containsVertex(e)||r(`Link to off-mesh vertex[${t}]`)}i++}const a=this.vertices,h=a.length;n="Vertex";for(let t=0;t<h;t++){i=t;const e=a[t];e.validate(r);const n=e.edges,s=n.length;for(let t=0;t<s;t++){const e=n[t];this.containsEdge(e)||r(`Link to off-mesh edge[${t}]`)}const o=e.faces,h=o.length;for(let t=0;t<h;t++){const e=o[t];this.containsFace(e)||r(`Link to off-mesh face[${t}]`)}}return e}clone(){const t=new st;return t.add(this),t}buildVertexMapping(){const t=new Map,e=this.vertices,n=e.length;for(let i=0;i<n;i++){const n=e[i];t.set(n.index,n)}return t}_addWithVertexMap(t,e){const n=t.getFaces();for(let t of n)this.addFaceCopy(t,e)}addFaceCopy(t,e){const n=new nt;tt(n.normal,t.normal);const i=t.vertices;for(let t=0;t<3;t++){const r=i[t];let s=e.get(r.index);void 0===s&&(s=new it,s.index=r.index,s.x=r.x,s.y=r.y,s.z=r.z,e.set(r.index,s),this.addVertex(s)),n.setVertexAt(t,s),s.addUniqueFace(n)}this.addFace(n);const r=n.vertices,s=r[0],o=r[1],a=r[2],h=this.ensureEdge(s,o),c=this.ensureEdge(o,a),d=this.ensureEdge(a,s);h.addUniqueFace(n),c.addUniqueFace(n),d.addUniqueFace(n),n.addUniqueEdge(h),n.addUniqueEdge(c),n.addUniqueEdge(d)}add(t){const e=this.buildVertexMapping();this._addWithVertexMap(t,e)}addVertex(t){this.vertices.push(t)}addUniqueVertex(t){W(this.vertices,t)}removeVertex(t){var e;e=t,H(this.vertices,e)}containsVertex(t){return-1!==this.vertices.indexOf(t)}addEdge(t){this.__edges.add(t)}addUniqueEdge(t){this.__edges.add(t)}removeEdge(t){var e;e=t,this.__edges.delete(e)}containsEdge(t){return this.__edges.has(t)}addFace(t){this.__faces.add(t)}injectManyFaces(t){for(let e of t)this.injectFace(e)}injectFace(t){this.addFace(t);const e=t.edges,n=e.length;for(let t=0;t<n;t++){const n=e[t];this.addUniqueEdge(n)}const i=t.vertices,r=i.length;for(let t=0;t<r;t++){const e=i[t];this.addUniqueVertex(e)}}removeFace(t){var e;e=t,this.__faces.delete(e)}containsFace(t){return this.__faces.has(t)}ensureEdge(t,e){const n=t.edges,i=n.length;for(let r=0;r<i;r++){const i=n[r];if(G(i,t)===e)return i}const r=new K;return r.v0=t,r.v1=e,t.edges.push(r),e.edges.push(r),this.__edges.add(r),r}mergeEdges(){const t=this.getEdges();for(let e of t){const n=e.v0,i=e.v1;for(let r of t){if(e===r)continue;const t=r.v0,s=r.v1;if(n===t){if(i!==s)continue}else{if(n!==s)continue;if(i!==t)continue}this.removeEdge(r),e.merge(r)}}}computeEdgeSquaredLengths(){const t=this.getEdges();for(let e of t)e.computeSquaredLength()}build(t,e){const n=e.length,i=t.length/3,r=this.vertices;for(let e=0;e<i;e++){const n=3*e,i=new it;i.index=e,i.x=t[n],i.y=t[n+1],i.z=t[n+2],r[e]=i}const s=n/3,o=this.getFaces();for(let t=0;t<s;t++){const n=3*t,i=e[n],s=e[n+1],a=e[n+2],h=r[i],c=r[s],d=r[a],u=new nt;u.index=t;const l=this.ensureEdge(h,c),f=this.ensureEdge(c,d),g=this.ensureEdge(d,h);l.faces.push(u),f.faces.push(u),g.faces.push(u),u.vertices.push(h,c,d),u.edges.push(l,f,g),h.faces.push(u),c.faces.push(u),d.faces.push(u),o.add(u)}}toString(){return`TopoMesh{ vertices: ${rt(this.vertices.length)}, edges: ${rt(this.getEdges().size)}, faces: ${rt(this.getFaces().size)} }`}}st.prototype.isTopoMesh=!0,self.Lib={build_bvh(t,e){const n=new x;return function(t,e,n){const i=n.length/3;t.setLeafCount(i),t.initialize_structure();for(let r=0;r<i;r++){const i=3*r;b(t,r,e,n[i],n[i+1],n[i+2])}t.build()}(n,t,e),n},Sampler2D:D,BufferedGeometryArraysBuilder:P,tensionOptimizeUV:function(t,e,n,i){const r=new st;r.build(t,n),r.computeEdgeSquaredLengths();const s=t.length/3;for(let t=0;t<i;t++)t:for(let t=0;t<s;t++){const n=r.vertices[t],i=n.edges,s=i.length;if(0===s)continue;let o=0,a=0,h=0;for(let t=0;t<s;t++){const r=i[t];if(r.isTopologyBorder())continue t;const s=2*r.getOtherVertex(n).index,c=e[s],d=e[s+1],u=1/r.lengthSqr;o+=c*u,a+=d*u,h+=u}const c=o/h,d=a/h,u=2*n.index;e[u]=c,e[u+1]=d}},sampler2d_channel_compute_min:function(t,e=0){const n=t.itemSize,i=t.data,r=i.length;if(0===r)return;let s=i[e],o=e;for(let t=e+n;t<r;t+=n){const e=i[t];s>e&&(s=e,o=t)}const a=t.width,h=o/n|0;return{index:o,value:s,x:h%a,y:h/a|0}},sampler2d_channel_compute_max:function(t,e=0){const n=t.itemSize,i=t.data,r=i.length;if(0===r)return;let s=i[e],o=e;for(let t=e+n;t<r;t+=n){const e=i[t];s<e&&(s=e,o=t)}const a=t.width,h=o/n|0;return{index:o,value:s,x:h%a,y:h/a|0}}};
1
+ function t(t,e){const n=t.length;if(n!==e.length)return!1;for(let i=0;i<n;i++)if(t[i]!==e[i])return!1;return!0}class e{appendDescriptionOf(t){throw new Error("Not Implemented")}appendList(t,e,n,i){throw new Error("Not Implemented")}appendText(t){throw new Error("Not Implemented")}appendValue(t){throw new Error("Not Implemented")}appendValueList(t,e,n,i){throw new Error("Not Implemented")}}class n{describeTo(t){throw new Error("Not Implemented")}}class i extends n{value;constructor(t){super(),this.value=t}describeTo(t){t.appendValue(this.value)}}class r{#t;constructor(t){this.#t=t}*[Symbol.iterator](){for(const t of this.#t)yield new i(t)}}class s extends e{appendDescriptionOf(t){return t.describeTo(this),this}#e(t){this.appendText('"'),this.appendText(t),this.appendText('"')}appendValue(t){return null==t?this.appendText("null"):void 0===t?this.appendText("undefined"):"string"==typeof t?this.#e(t):"number"==typeof t?this.appendText(function(t){return String(t)}(t)):Array.isArray(t)?this.appendValueList("[",", ","]",t):(this.appendText("<"),this.appendText(function(t){try{return String(t)}catch(t){return"VALUE@0"}}(t)),this.appendText(">")),this}appendValueList(t,e,n,i){return this.appendList(t,e,n,new r(i)),this}appendList(t,e,n,i){let r=!1;this.appendText(t);const s=i[Symbol.iterator]();for(let t=s.next();!0!==t.done;t=s.next())r&&this.appendText(e),this.appendDescriptionOf(t.value),r=!0;return this.appendText(n),this}}class o extends s{value="";appendText(t){return this.value+=t,this}}function a(t,e){if(!t)throw new Error(e||"AssertionError")}function h(t,e,n,i,r){let s,o,a;for(a=0;a<r;a++)s=e+a,o=i+a,n[o]=t[s]}a.enum=function(t,e,n="value"){for(let n in e)if(e[n]===t)return;throw new Error(`${n}(=${t}) is not a valid enumerable value, valid values are: [${Object.values(e).join(", ")}]`)},a.notEqual=function(t,e,n){a(t!==e,n)},a.notOk=function(t,e){a(!t,e)},a.equal=function(t,e,n){if(t!==e){const i=`${t} !== ${e}`;throw new Error(void 0!==n&&""!==n?`${n}. ${i}`:i)}},a.logicalyEqual=function(t,e,n){},a.ok=a,a.greaterThan=function(t,e,n){if(!(t>e)){let i="";throw void 0!==n&&(i+=n+". "),i+=`Expected ${t} > ${e}.`,new Error(i)}},a.greaterThanOrEqual=function(t,e,n){if(!(t>=e)){let i="";throw void 0!==n&&(i+=n+". "),i+=`Expected ${t} >= ${e}.`,new Error(i)}},a.lessThan=function(t,e,n){if(!(t<e)){let i="";throw void 0!==n&&(i+=n+". "),i+=`Expected ${t} < ${e}.`,new Error(i)}},a.lessThanOrEqual=function(t,e,n){if(!(t<=e)){let i="";throw void 0!==n&&(i+=n+". "),i+=`Expected ${t} <= ${e}.`,new Error(i)}},a.typeOf=function(t,e,n="value"){const i=typeof t;if(i!==e)throw new Error(`expected ${n} to be ${e}, instead was '${i}'(=${t})`)},a.arrayHas=function(t,e,n="Array does not contain the item"){},a.arrayHasNo=function(t,e,n="Array contains the item"){},a.arrayEqual=function(e,n,i="Arrays are not equal"){if(!t(e,n))throw new Error(i)},a.isInstanceOf=function(t,e,n="value",i=e.name){},a.isNumber=function(t,e="value"){const n=typeof t;if("number"!==n)throw new Error(`expected ${e} to be a number, instead was '${n}'(=${t})`)},a.isString=function(t,e="value"){const n=typeof t;if("string"!==n)throw new Error(`expected ${e} to be a string, instead was '${n}'(=${t})`)},a.isBoolean=function(t,e="value"){const n=typeof t;if("boolean"!==n)throw new Error(`expected ${e} to be a boolean, instead was '${n}'(=${t})`)},a.isFunction=function(t,e="value"){const n=typeof t;if("function"!==n)throw new Error(`expected ${e} to be a function, instead was '${n}'(=${t})`)},a.isObject=function(t,e="value"){const n=typeof t;if("object"!==n)throw new Error(`expected ${e} to be an object, instead was '${n}'(=${t})`)},a.isInteger=function(t,e="value"){if(!Number.isInteger(t))throw new Error(`${e} must be an integer, instead was ${t}`)},a.isNonNegativeInteger=function(t,e="value"){if(t<0)throw new Error(`${e} must be >= 0, instead was ${t}`)},a.isArray=function(t,e="value"){if(!Array.isArray(t))throw new Error(`expected ${e} to be an array, instead was something else (typeof ='${typeof t}')`)},a.isArrayLike=function(t,e="value"){if(!(Array.isArray(t)||(n=t,n instanceof Int8Array||n instanceof Uint8Array||n instanceof Uint8ClampedArray||n instanceof Int16Array||n instanceof Uint16Array||n instanceof Int32Array||n instanceof Uint32Array||n instanceof Float32Array||n instanceof Float64Array)))throw new Error(`expected ${e} to be an array-like structure, instead was something else (typeof ='${typeof t}')`);var n},a.defined=function(t,e="value"){if(void 0===t)throw new Error(`${e} is undefined`)},a.isNull=function(t,e){if(null!==t)throw new Error(`${e} is NOT null`)},a.notNull=function(t,e="value"){if(null===t)throw new Error(`${e} is null`)},a.notNaN=function(t,e="value"){if(Number.isNaN(t))throw new Error(`${e} must be a valid number, instead was NaN`)},a.isFiniteNumber=function(t,e="value"){if(!Number.isFinite(t))throw new Error(`${e} must be a finite number, instead was ${t}`)},a.that=function(t,e,n){if(n.matches(t))return;const i=new o;throw i.appendText(`Expected ${e} to be `),n.describeTo(i),i.appendText(" instead "),n.describeMismatch(t,i),new Error(i.value)};const c=new Uint32Array(781250);function d(t,e){return t<e?e:t}function u(t,e){return t<e?t:e}function l(t,e,n,i,r,s){const o=n[i+0],a=n[i+1],h=n[i+2],c=n[i+3],l=n[i+4],f=n[i+5],g=r[s+0],_=r[s+1],p=r[s+2],y=r[s+3],m=r[s+4],w=r[s+5],v=u(o,g),x=u(a,_),b=u(h,p),A=d(c,y),E=d(l,m),$=d(f,w);t[e+0]=v,t[e+1]=x,t[e+2]=b,t[e+3]=A,t[e+4]=E,t[e+5]=$}function f(t,e,n,i,r,s,o,a){t[e]=n,t[e+1]=i,t[e+2]=r,t[e+3]=s,t[e+4]=o,t[e+5]=a}function g(t,e,n,i,r,s){const o=i-t,a=s-n;return(r-e)*(o+a)+a*o}function _(t){let e=t;return e=50331903&(e|e<<16),e=50393103&(e|e<<8),e=51130563&(e|e<<4),e=153391689&(e|e<<2),e}function p(t,e,n){let i=t;return i<e&&(i=e),i<n&&(i=n),i}function y(t,e,n){let i=t;return i>e&&(i=e),i>n&&(i=n),i}function m(t,e,n){const i=t[n],r=t[n+1],s=t[n+2];f(t,e,i,r,s,i,r,s)}function w(t,e,n){const i=t[e],r=t[e+1],s=t[e+2];return function(t,e,n,i){const r=i[0],s=i[1],o=i[2],a=1023*(t-r)/(i[3]-r),h=1023*(e-s)/(i[4]-s),c=1023*(n-o)/(i[5]-o);return function(t,e,n){return _(t)|_(e)<<1|_(n)<<2}(Math.round(a),Math.round(h),Math.round(c))}(.5*(i+t[e+3]),.5*(r+t[e+4]),.5*(s+t[e+5]),n)}c.pointer=0;const v=c;class x{__data_buffer;__data_float32;__data_uint32;__node_count_binary=0;__node_count_leaf=0;constructor(){this.data=new ArrayBuffer(320)}estimateByteSize(){return this.data.byteLength+248}getTotalBoxCount(){return this.__node_count_binary+this.__node_count_leaf}get binary_node_count(){return this.__node_count_binary}get leaf_node_count(){return this.__node_count_leaf}getLeafBlockAddress(){return 6*this.__node_count_binary}get float32(){return this.__data_float32}get uint32(){return this.__data_uint32}set data(t){this.__data_buffer=t,this.__data_float32=new Float32Array(this.__data_buffer),this.__data_uint32=new Uint32Array(this.__data_buffer)}get data(){return this.__data_buffer}getNodeAddress(t){const e=this.__node_count_binary,n=t-e;return n<0?6*t:6*e+7*n}initialize_structure(){const t=4*(6*this.__node_count_binary+7*this.__node_count_leaf);this.__data_buffer.byteLength<t&&(this.data=new ArrayBuffer(t))}setLeafCount(t){this.__node_count_leaf=t;const e=function(t){let e=t-1;return e|=e>>1,e|=e>>2,e|=e>>4,e|=e>>8,e|=e>>16,e++,e}(t);this.__node_count_binary=t<=1?e:e-1}getLeafAddress(t){return 7*t+6*this.__node_count_binary}setLeafData(t,e,n,i,r,s,o,a){const h=this.getLeafAddress(t);f(this.__data_float32,h,n,i,r,s,o,a),this.__data_uint32[h+6]=e}readBounds(t,e,n){h(this.__data_float32,t,e,n,6)}readLeafPayload(t){const e=this.getLeafBlockAddress()+7*t+6;return this.__data_uint32[e]}compute_total_surface_area(){let t=0;const e=new Float32Array(6);for(let n=0;n<this.getTotalBoxCount();n++){let i;i=n<this.__node_count_binary?6*n:7*(n-this.__node_count_binary)+this.getLeafBlockAddress(),this.readBounds(i,e,0),t+=g(e[0],e[1],e[2],e[3],e[4],e[5])}return t}__compute_bounds_area_of_3_boxes(t,e,n){const i=this.__data_float32;return g(y(i[t+0],i[e+0],i[n+0]),y(i[t+1],i[e+1],i[n+1]),y(i[t+2],i[e+2],i[n+2]),p(i[t+3],i[e+3],i[n+3]),p(i[t+4],i[e+4],i[n+4]),p(i[t+5],i[e+5],i[n+5]))}__fitness_function_should_swap_leaves_sah(t,e){const n=d(t-1,0),i=u(t+1,this.__node_count_leaf-1),r=this.getLeafBlockAddress(),s=7*t+r,o=7*n+r,a=7*i+r,h=7*e+r,c=7*d(e-1,0)+r,l=7*u(e+1,this.__node_count_leaf-1)+r;return this.__compute_bounds_area_of_3_boxes(o,s,a)+this.__compute_bounds_area_of_3_boxes(c,h,l)-(this.__compute_bounds_area_of_3_boxes(o,h,a)+this.__compute_bounds_area_of_3_boxes(c,s,l))}sort_bubble_sah(){const t=this.__node_count_leaf;for(let e=0;e<t;e++)for(let n=e+1;n<t;n++)this.__fitness_function_should_swap_leaves_sah(e,n)>0&&this.__swap_leaves(e,n)}sort_morton(t){const e=6*this.__node_count_binary;if(this.__node_count_leaf<2)return;let n,i,r=2;v[0]=0,v[1]=this.__node_count_leaf-1;const s=this.__data_float32;for(;r>0;){r-=2;const o=v[r+1],a=v[r];n=a,i=o;const h=w(s,7*(a+o>>1)+e,t);for(;n<=i;){for(;w(s,7*n+e,t)<h;)n++;for(;w(s,7*i+e,t)>h;)i--;n<=i&&(n!==i&&this.__swap_leaves(n,i),n++,i--)}a<i&&(v[r++]=a,v[r++]=i),n<o&&(v[r++]=n,v[r++]=o)}}__swap_leaves(t,e){const n=this.getLeafBlockAddress(),i=7*t+n,r=7*e+n;!function(t,e,n,i,r){for(let r=0;r<7;r++){const s=e+r,o=i+r,a=n[o];n[o]=t[s],t[s]=a}}(this.__data_float32,i,this.__data_float32,r)}build(){const t=this.__node_count_binary,e=6*t;let n,i,r,s,o=Math.floor(Math.log(t)/Math.log(2));r=Math.pow(2,o),i=6*(r-1);const a=this.__node_count_leaf,c=this.__data_float32;for(n=0;n<r;n++){const t=n<<1,r=t+1,s=e+7*t;r<a?l(c,i,c,s,c,e+7*r):t<a?h(c,s,c,i,6):m(this.__data_float32,i,i-6),i+=6}for(o--;o>=0;o--)for(r=1<<o,s=r-1,n=0;n<r;n++){const t=6*(1+(s<<1));l(c,6*s,c,t,c,t+6),s++}}}function b(t,e,n,i,r,s){const o=t.getLeafAddress(e);!function(t,e,n,i,r,s){const o=3*i,a=3*r,h=3*s,c=n[o],d=n[o+1],u=n[o+2],l=n[a],f=n[a+1],g=n[a+2],_=n[h],m=n[h+1],w=n[h+2];t[e]=y(c,l,_),t[e+1]=y(d,f,m),t[e+2]=y(u,g,w),t[e+3]=p(c,l,_),t[e+4]=p(d,f,m),t[e+5]=p(u,g,w)}(t.__data_float32,o,n,i,r,s),t.__data_uint32[o+6]=e}const A=[],E=[],$="undefined"!=typeof Uint8Array?Uint8Array:Array,S="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(let t=0,e=64;t<e;++t)A[t]=S[t],E[S.charCodeAt(t)]=t;function U(t,e,n){const i=[];for(let s=e;s<n;s+=3){const e=(t[s]<<16&16711680)+(t[s+1]<<8&65280)+(255&t[s+2]);i.push(A[(r=e)>>18&63]+A[r>>12&63]+A[r>>6&63]+A[63&r])}var r;return i.join("")}E["-".charCodeAt(0)]=62,E["_".charCodeAt(0)]=63;class F{static encode(t){return function(t){let e;const n=t.length,i=n%3,r=[],s=16383,o=n-i;for(let e=0;e<o;e+=s){const n=U(t,e,e+s>o?o:e+s);r.push(n)}return 1===i?(e=t[n-1],r.push(A[e>>2]+A[e<<4&63]+"==")):2===i&&(e=(t[n-2]<<8)+t[n-1],r.push(A[e>>10]+A[e>>4&63]+A[e<<2&63]+"=")),r.join("")}(new Uint8Array(t))}static decode(t){return function(t){var e,n,i=function(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var n=t.indexOf("=");return-1===n&&(n=e),[n,n===e?0:4-n%4]}(t),r=i[0],s=i[1],o=new $(function(t,e,n){return 3*(e+n)/4-n}(0,r,s)),a=0,h=s>0?r-4:r;for(n=0;n<h;n+=4)e=E[t.charCodeAt(n)]<<18|E[t.charCodeAt(n+1)]<<12|E[t.charCodeAt(n+2)]<<6|E[t.charCodeAt(n+3)],o[a++]=e>>16&255,o[a++]=e>>8&255,o[a++]=255&e;return 2===s&&(e=E[t.charCodeAt(n)]<<2|E[t.charCodeAt(n+1)]>>4,o[a++]=255&e),1===s&&(e=E[t.charCodeAt(n)]<<10|E[t.charCodeAt(n+1)]<<4|E[t.charCodeAt(n+2)]>>2,o[a++]=e>>8&255,o[a++]=255&e),o}(t).buffer}}const z="uint8",C="uint16",V="uint32",B="int8",q="int16",L="int32",M="float32",T="float64",I={[z]:Uint8Array,[C]:Uint16Array,[V]:Uint32Array,[B]:Int8Array,[q]:Int16Array,[L]:Int32Array,float16:Uint16Array,[M]:Float32Array,[T]:Float64Array};function N(t){switch(Object.getPrototypeOf(t).constructor){case Uint8Array:case Uint8ClampedArray:return z;case Uint16Array:return C;case Uint32Array:return V;case Int8Array:return B;case Int16Array:return q;case Int32Array:return L;case Float32Array:return M;case Float64Array:return T;default:throw new Error("unsupported constructor type")}}function O(t,e,n){return t<e?e:t>n?n:t}function k(t,e,n){return(e-t)*n+t}function j(t,e,n,i,r){return.5*(i-e+(2*e-5*n+4*i-r+(3*(n-i)+r-e)*t)*t)*t+n}class D{constructor(t=[],e=1,n=0,i=0){if(!Number.isInteger(e)||e<0)throw new Error(`itemSize must be a non-negative integer, instead was ${e}`);if(!Number.isInteger(n)||n<0)throw new Error(`width must be a non-negative integer, instead was ${n}`);if(!Number.isInteger(i)||n<0)throw new Error(`height must be a non-negative integer, instead was ${i}`);if(void 0===t)throw new Error("data was undefined");if(t.length<n*i*e)throw new Error(`Buffer underflow, data.length(=${t.length}) is too small. Expected at least ${n*i*e}`);this.width=n,this.height=i,this.itemSize=e,this.data=t,this.version=0}get(t,e,n){throw new Error("Deprecated method, use sampleBilinear instead")}sampleCatmullRomUV(t,e,n){const i=this.itemSize;for(let r=0;r<i;r++)n[r]=this.sampleChannelCatmullRomUV(t,e,r)}sampleChannelCatmullRomUV(t,e,n){const i=t*this.width-.5,r=e*this.height-.5;return this.sampleChannelCatmullRom(i,r,n)}sampleChannelCatmullRom(t,e,n){const i=Math.floor(t),r=Math.floor(e),s=t-i,o=e-r,a=s*(s*(1-.5*s)-.5),h=o*(o*(1-.5*o)-.5),c=s*(.5+s*(2-1.5*s)),d=o*(.5+o*(2-1.5*o)),u=s*s*(.5*s-.5),l=o*o*(.5*o-.5),f=1+s*s*(1.5*s-2.5)+c,g=1+o*o*(1.5*o-2.5)+d,_=i-1,p=r-1,y=i+2,m=r+2,w=i+c/f,v=r+d/g;let x=0;return x+=this.sampleChannelBilinear(_,p,n)*a*h,x+=this.sampleChannelBilinear(w,p,n)*f*h,x+=this.sampleChannelBilinear(y,p,n)*u*h,x+=this.sampleChannelBilinear(_,v,n)*a*g,x+=this.sampleChannelBilinear(w,v,n)*f*g,x+=this.sampleChannelBilinear(y,v,n)*u*g,x+=this.sampleChannelBilinear(_,m,n)*a*l,x+=this.sampleChannelBilinear(w,m,n)*f*l,x+=this.sampleChannelBilinear(y,m,n)*u*l,x}sampleBicubicUV(t,e,n){const i=this.itemSize;for(let r=0;r<i;r++)n[r]=this.sampleChannelBicubicUV(t,e,r)}sampleBicubic(t,e,n,i){const r=this.itemSize;for(let s=0;s<r;s++)n[s+i]=this.sampleChannelBicubic(t,e,s)}sampleChannelBicubicUV(t,e,n){const i=t*this.width,r=e*this.height;return this.sampleChannelBicubic(i-.5,r-.5,n)}sampleChannelBicubic(t,e,n){const i=this.itemSize,r=this.width,s=this.height,o=this.data,a=r*i,h=r-1,c=s-1,l=O(t,0,h),f=O(e,0,c),g=0|l,_=0|f,p=l-g,y=f-_,m=d(0,g-1),w=d(0,_-1),v=u(h,g+1),x=u(c,_+1),b=u(h,v+1),A=w*a+n,E=_*a+n,$=x*a+n,S=u(c,x+1)*a+n,U=m*i,F=g*i,z=v*i,C=b*i,V=o[A+U],B=o[A+F],q=o[A+z],L=o[A+C],M=o[E+U],T=o[E+F],I=o[E+z],N=o[E+C],k=o[$+U],D=o[$+F],R=o[$+z],J=o[$+C],P=o[S+U],H=o[S+F],W=o[S+z],G=o[S+C],Y=j(p,V,B,q,L),K=j(p,M,T,I,N),Q=j(p,k,D,R,J),X=j(p,P,H,W,G);return j(y,Y,K,Q,X)}sampleBilinearUV(t,e,n,i=0){const r=this.itemSize;for(let s=0;s<r;s++)n[s+i]=this.sampleChannelBilinearUV(t,e,s)}sampleBilinear(t,e,n,i=0){const r=this.itemSize;for(let s=0;s<r;s++)n[s+i]=this.sampleChannelBilinear(t,e,s)}sampleChannelBilinearUV(t,e,n){const i=t*this.width-.5,r=e*this.height-.5;return this.sampleChannelBilinear(i,r,n)}sampleChannelBilinear(t,e,n){const i=this.itemSize,r=this.width,s=r*i,o=this.height-1,a=O(t,0,r-1),h=O(e,0,o),c=a>>>0,d=h>>>0,u=d*s,l=c*i+n,f=u+l;let g,_;g=a===c?c:c+1,_=h===d?d:d+1;const p=this.data,y=p[f];if(c===g&&d===_)return y;const m=a-c,w=h-d,v=g*i+n,x=_*s,b=x+l,A=x+v,E=p[u+v],$=p[b],S=p[A],U=k(y,E,m),F=k($,S,m);return k(U,F,w)}sampleNearestUV(t,e,n){const i=this.width,r=this.height,s=Math.round(t*i-.5),o=Math.round(e*r-.5);this.read(O(s,0,i-1),O(o,0,r-1),n)}readChannel(t,e,n){const i=(e*this.width+t)*this.itemSize+n;return this.data[i]}read(t,e,n){const i=this.width,r=this.itemSize,s=(e*i+t)*r;for(let t=0;t<r;t++)n[t]=this.data[s+t]}write(t,e,n){const i=this.width,r=this.itemSize,s=(e*i+t)*r;for(let t=0;t<r;t++)this.data[s+t]=n[t]}sample(t,e,n){const i=[];return this.sampleBilinear(t*(this.width-1),e*(this.height-1),i,0),n.readFromArray(i),i[0]}point2index(t,e){return t+e*this.width}index2point(t,e){const n=this.width,i=t%n,r=t/n|0;e.set(i,r)}copy(t,e,n,i,r,s,o){const a=Math.min(s,t.width-e,this.width-i),h=Math.min(o,t.height-n,this.height-r),c=this.itemSize,d=t.itemSize,u=Math.min(c,d),l=c*this.width,f=d*t.width,g=t.data,_=this.data;let p,y,m;for(y=0;y<h;y++){const t=(y+r)*l,s=(y+n)*f;for(p=0;p<a;p++){const n=t+(p+i)*c,r=s+(p+e)*d;for(m=0;m<u;m++)_[n+m]=g[r+m]}}this.version++}zeroFill(t,e,n,i){const r=O(t,0,this.width),s=O(e,0,this.height),o=O(t+n,0,this.width),a=O(e+i,0,this.height),h=this.data,c=this.itemSize,d=c*this.width,u=r*c,l=o*c;let f;for(f=s;f<a;f++){const t=f*d;h.fill(0,t+u,t+l)}this.version++}channelFill(t,e){const n=this.itemSize,i=this.data,r=i.length;for(let s=t;s<r;s+=n)i[s]=e;this.version++}fill(t,e,n,i,r){const s=this.width,o=this.height,a=O(t,0,s),h=O(e,0,o),c=O(t+n,0,s),d=O(e+i,0,o),u=this.data,l=this.itemSize,f=l*s;let g,_,p;for(g=h;g<d;g++){const t=g*f;for(_=a;_<c;_++){const e=t+_*l;for(p=0;p<l;p++)u[e+p]=r[p]}}this.version++}writeChannel(t,e,n,i){const r=(e*this.width+t)*this.itemSize+n;this.data[r]=i,this.version++}set(t,e,n){const i=this.data,r=this.itemSize,s=r*this.width*e+t*r;for(let t=0;t<r;t++)i[s+t]=n[t];this.version++}traverseCircle(t,e,n,i){let r,s;const o=0|t,a=0|e,h=n*n,c=Math.ceil(n);for(s=-c;s<=c;s++){const t=s*s;for(r=-c;r<=c;r++)r*r+t<=h&&i(o+r,a+s,this)}}resize(t,e,n=!0){const i=this.width,r=this.height;if(i===t&&r===e)return;const s=this.itemSize,o=t*e*s,a=this.data,h=new(function(t){if(t instanceof Int8Array)return Int8Array;if(t instanceof Int16Array)return Int16Array;if(t instanceof Int32Array)return Int32Array;if(t instanceof Uint8Array)return Uint8Array;if(t instanceof Uint8ClampedArray)return Uint8ClampedArray;if(t instanceof Uint16Array)return Uint16Array;if(t instanceof Uint32Array)return Uint32Array;if(t instanceof Float32Array)return Float32Array;if(t instanceof Float64Array)return Float64Array;if(Array.isArray(t))return Array;throw new TypeError("Unsupported array type")}(a))(o);if(n)if(t===i)h.set(a.subarray(0,Math.min(a.length,o)));else{const n=u(e,r),o=u(t,i);for(let e=0;e<n;e++)for(let n=0;n<o;n++){const r=(e*t+n)*s,o=(e*i+n)*s;for(let t=0;t<s;t++)h[r+t]=a[o+t]}}this.width=t,this.height=e,this.data=h,this.version++}computeByteSize(){let t;return t=Array.isArray(this.data)?8*this.data.length:this.data.buffer.byteLength,t+280}equals(e){return this.width===e.width&&this.height===e.height&&this.itemSize===e.itemSize&&function(e,n){if(e===n)return!0;const i=e.length;if(i!==n.length)return!1;if(0===i)return!0;if(i<128)return t(e,n);const r=e.byteLength;if(r!==n.byteLength)return!1;const s=e.constructor;if(s!==n.constructor)return!1;const o=e.buffer,a=n.buffer;if(o===a&&e.byteOffset===n.byteOffset)return!0;let h=e,c=n;const d=s.BYTES_PER_ELEMENT;return d<4&&r%4==0?(h=new Uint32Array(o,e.byteOffset,r/4),c=new Uint32Array(a,n.byteOffset,r/4)):d<2&&r%2==0&&(h=new Uint16Array(o,e.byteOffset,r/2),c=new Uint16Array(a,n.byteOffset,r/2)),t(h,c)}(this.data,e.data)}hash(){let t=((65535&this.width)<<16|65535&this.height)^this.itemSize;const e=this.data.length,n=Math.max(1,Math.ceil(e/509));return t^=function(t,e,n,i){let r=n;for(let e=0;e<n;e+=i)r=(r<<5)-r+(t[e]>>>0);return r>>>0}(this.data,0,e,n),t}clone(){let t;return t=Array.isArray(this.data)?this.data.slice():new(0,this.data.constructor)(this.data),new D(t,this.itemSize,this.width,this.height)}toJSON(){const t=F.encode(this.data.buffer);return{height:this.height,width:this.width,itemSize:this.itemSize,type:N(this.data),data:t}}fromJSON({height:t,width:e,itemSize:n,type:i,data:r}){const s=function(t){const e=I[t];if(void 0===e)throw new Error(`Unsupported data type '${t}'`);return e}(i);if("string"==typeof r){const t=F.decode(r);this.data=new s(t)}else{if(!Array.isArray(r))throw new Error("Unsupported data format");this.data=new s(r)}this.height=t,this.width=e,this.itemSize=n}static uint8clamped(t,e,n){const i=new Uint8ClampedArray(e*n*t);return new D(i,t,e,n)}static uint8(t,e,n){const i=new Uint8Array(e*n*t);return new D(i,t,e,n)}static uint16(t,e,n){const i=new Uint16Array(e*n*t);return new D(i,t,e,n)}static uint32(t,e,n){const i=new Uint32Array(e*n*t);return new D(i,t,e,n)}static int8(t,e,n){const i=new Int8Array(e*n*t);return new D(i,t,e,n)}static int16(t,e,n){const i=new Int16Array(e*n*t);return new D(i,t,e,n)}static int32(t,e,n){const i=new Int32Array(e*n*t);return new D(i,t,e,n)}static float32(t,e,n){const i=new Float32Array(e*n*t);return new D(i,t,e,n)}static float64(t,e,n){const i=new Float64Array(e*n*t);return new D(i,t,e,n)}}function R(t,e,n,i){const r=n[i],s=n[i+1],o=n[i+2];t[e]+=r,t[e+1]+=s,t[e+2]+=o}function J(t,e,n,i,r,s,o,a,h,c,d){const u=h-s,l=c-o,f=d-a,g=n-s,_=i-o,p=r-a,y=l*p-f*_,m=f*g-u*p,w=u*_-l*g,v=function(t,e,n){return t*t+e*e+n*n}(y,m,w);if(0===v)return t[e]=0,t[e+1]=1,void(t[e+2]=0);const x=1/Math.sqrt(v),b=y*x,A=m*x,E=w*x;t[e]=b,t[e+1]=A,t[e+2]=E}function P(t,e,n,i,r,s){const o=3*n,a=3*i,h=3*r;J(t,e,s[o],s[o+1],s[o+2],s[a],s[a+1],s[a+2],s[h],s[h+1],s[h+2])}function H(t,e,n){return Math.sqrt(t*t+e*e+n*n)}function W(t,e,n,i){const r=n[i],s=n[i+1],o=n[i+2],a=1/H(r,s,o);t[e]=r*a,t[e+1]=s*a,t[e+2]=o*a}D.prototype.isSampler2D=!0,D.typeName="Sampler2D";const G=new Float64Array(3),Y={build:function(t,e,n,i,r,s){const o=n.x*s,a=n.y*s,h=o-1,c=a-1;let d=0,u=0;const l=o*a,f=new Float32Array(3*l),g=new Float32Array(3*l),_=new Float32Array(2*l);let p,y;const m=n.y/r.y/c,w=n.x/r.x/h,v=e.y/r.y,x=e.x/r.x,b=r.x*i.x,A=r.y*i.y;let E,$,S;for(p=0;p<a;p++){const e=p*m+v;for(S=e*A,y=0;y<o;y++){const n=y*w+x;E=n*b,$=t.sampleChannelBicubicUV(n,e,0),f[d]=E,f[d+1]=$,f[d+2]=S,_[u]=n,_[u+1]=e,d+=3,u+=2}}d=0;const U=new(f.length/3>65535?Uint32Array:Uint16Array)(h*c*6);for(p=0;p<c;p++)for(y=0;y<h;y++){const t=y+o*p,e=y+o*(p+1),n=y+1+o*(p+1),i=y+1+o*p;U[d]=t,U[d+1]=e,U[d+2]=i,U[d+3]=e,U[d+4]=n,U[d+5]=i,d+=6}return function(t,e,n){const i=n.length;for(let r=0;r<i;r+=3){const i=n[r],s=n[r+1],o=n[r+2];P(G,0,i,s,o,t),R(e,3*i,G,0),R(e,3*s,G,0),R(e,3*o,G,0)}!function(t,e=0,n=t.length-e){const i=e+n;for(let n=e;n<i;n+=3)W(t,n,t,n)}(e)}(f,g,U),{indices:U,vertices:f,normals:g,uvs:_}}};var K,Q="undefined"!=typeof Float32Array?Float32Array:Array;function X(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t}function Z(t,e){return-1===t.indexOf(e)&&(t.push(e),!0)}function tt(){}function et(t,e=","){return t.toString().replace(/\B(?=(\d{3})+(?!\d))/g,e)}function nt(t,e){return t.v0===e?t.v1:t.v1===e?t.v0:null}function it(t,e,n=0,i=t.length){const r=n+i;for(let i=n;i<r;i++)if(t[i]===e)return t.splice(i,1),!0;return!1}Math.hypot||(Math.hypot=function(){for(var t=0,e=arguments.length;e--;)t+=arguments[e]*arguments[e];return Math.sqrt(t)}),K=new Q(3),Q!=Float32Array&&(K[0]=0,K[1]=0,K[2]=0);let rt=0;class st{constructor(){this.index=rt++,this.v0=null,this.v1=null,this.faces=[],this.lengthSqr=-1}get byteSize(){return 128+8*this.faces.length+10}getVertexByIndex(t){if(0===t)return this.v0;if(1===t)return this.v1;throw new Error("Index out of bounds")}copy(t){this.v0=t.v0,this.v1=t.v1,this.lengthSqr=t.lengthSqr,this.faces=t.faces.slice()}clone(){const t=new st;return t.copy(this),t}validate(t){let e=!0;const n=this.faces,i=n.length;for(let r=0;r<i;r++)n[r].containsEdge(this)||(t(`Missing back-link from face[${r}]`),e=!1);return this.v0.containsEdge(this)||(t("Missing back-link from vertex v0"),e=!1),this.v1.containsEdge(this)||(t("Missing back-link from vertex v1"),e=!1),e}isLinked(){return this.v0.containsEdge(this)}unlink(){const t=this.v0,e=this.v1;t.removeEdge(this),t!==e&&e.removeEdge(this);const n=this.faces,i=n.length;for(let t=0;t<i;t++)n[t].removeEdge(this)}isDegenerateEdge(){return this.v0===this.v1}isTopologyBorder(){return 1===this.faces.length}get length(){return this.lengthSqr<0&&this.computeSquaredLength(),Math.sqrt(this.lengthSqr)}computeSquaredLength(){const t=this.v0,e=this.v1,n=t.x,i=t.y,r=t.z,s=n-e.x,o=i-e.y,a=r-e.z;this.lengthSqr=s*s+o*o+a*a}replaceVertex(t,e){t===this.v0&&(this.v0=e),t===this.v1&&(this.v1=e)}merge(t){const e=t.faces,n=this.faces,i=e.length;for(let r=0;r<i;r++){const i=e[r];i.removeEdge(t),-1===n.indexOf(i)&&(n.push(i),i.addUniqueEdge(this))}t.v0.removeEdge(t),t.v1.removeEdge(t)}containsFace(t){return-1!==this.faces.indexOf(t)}addFace(t){this.faces.push(t)}addUniqueFace(t){Z(this.faces,t)}removeFace(t){it(this.faces,t)}getOtherVertex(t){return nt(this,t)}containsVertex(t){return e=t,this.v0===e||this.v1===e;var e}containsBothVertices(t,e){return function(t,e,n){const i=t.v0,r=t.v1;return!(i!==e&&i!==n||r!==e&&r!==n)}(this,t,e)}containsSameVerticesAs(t){return this.containsBothVertices(t.v0,t.v1)}}function ot(t,e,n){const i=t.length;for(let r=0;r<i;r++)t[r]===e&&(t[r]=n)}st.prototype.isTopoEdge=!0;let at=0;class ht{constructor(){this.index=at++,this.vertices=[],this.edges=[],this.normal=[0,0,0]}get byteSize(){return 100+8*this.vertices.length+10+8*this.edges.length+10+24+10}copy(t){this.index=t.index,this.vertices=t.vertices.slice(),this.edges=t.edges.slice(),X(this.normal,t.normal)}clone(){const t=new ht;return t.copy(this),t}validate(t){let e=!0;const n=this.vertices,i=n.length;3!==i&&(t(`Expected number of vertices is 3, instead got ${i}`),e=!1);for(let r=0;r<i;r++)n[r].containsFace(this)||(t(`Missing back-link from vertex[${r}]`),e=!1);const r=this.edges,s=r.length;3!==s&&(t(`Expected number of edges is 3, instead got ${s}`),e=!1);for(let n=0;n<s;n++)r[n].containsFace(this)||(t(`Missing back-link from edge[${n}]`),e=!1);return e}isLinked(){return this.vertices[0].containsFace(this)}replaceEdge(t,e){ot(this.edges,t,e)}replaceVertex(t,e){ot(this.vertices,t,e)}isDegenerateTopology(){const t=this.vertices,e=t[0],n=t[1],i=t[2];return e===n||e===i||n===i}unlink(){const t=this.vertices,e=t.length;for(let n=0;n<e;n++)t[n].removeFace(this);const n=this.edges,i=n.length;for(let t=0;t<i;t++)n[t].removeFace(this)}addEdge(t){this.edges.push(t)}addUniqueEdge(t){return Z(this.edges,t)}removeEdge(t){it(this.edges,t)}containsEdge(t){return-1!==this.edges.indexOf(t)}computeNormal(){const t=this.vertices,e=t[0],n=t[1],i=t[2];!function(t,e,n,i){J(t,0,e[0],e[1],e[2],n[0],n[1],n[2],i[0],i[1],i[2])}(this.normal,e,n,i)}setVertexAt(t,e){this.vertices[t]=e}containsVertex(t){return-1!==this.vertices.indexOf(t)}getEdgeNeighbours(t,e){let n=0;const i=this.edges,r=i.length;for(let s=0;s<r;s++){const r=i[s].faces,o=r.length;for(let i=0;i<o;i++){const s=r[i];s!==this&&(t[e+n]=s,n++)}}return n}}ht.prototype.isTopoFace=!0;class ct{constructor(){this.index=0,this.edges=[],this.faces=[],this.x=0,this.y=0,this.z=0}get 0(){return this.x}get 1(){return this.y}get 2(){return this.z}get byteSize(){return 112+8*this.edges.length+10+8*this.faces.length+10}copy(t){this.x=t.x,this.y=t.y,this.z=t.z,this.index=t.index,this.faces=t.faces.slice(),this.edges=t.edges.slice()}clone(){const t=new ct;return t.copy(this),t}validate(t){let e=!0;const n=this.faces,i=n.length;for(let r=0;r<i;r++)n[r].containsVertex(this)||(t(`Missing back-link from face[${r}]`),e=!1);const r=this.edges,s=r.length;for(let n=0;n<s;n++)r[n].containsVertex(this)||(t(`Missing back-link from edge[${n}]`),e=!1);return e}distanceTo(t){return e=this.x,n=this.y,i=this.z,H(t.x-e,t.y-n,t.z-i);var e,n,i}addFace(t){this.faces.push(t)}addUniqueFace(t){return Z(this.faces,t)}containsFace(t){return-1!==this.faces.indexOf(t)}removeFace(t){it(this.faces,t)}addEdge(t){this.edges.push(t)}addUniqueEdge(t){return Z(this.edges,t)}replaceEdge(t,e){const n=this.edges,i=n.indexOf(t);n[i]=e}containsEdge(t){return-1!==this.edges.indexOf(t)}removeEdge(t){return it(this.edges,t)}replaceAnotherVertex(t){const e=t.faces,n=e.length;let i=0;for(;i<n;i++){const n=e[i];n.replaceVertex(t,this),this.addUniqueFace(n)}const r=t.edges,s=r.length;for(i=0;i<s;i++){const e=r[i];e.replaceVertex(t,this),this.addUniqueEdge(e)}}computeNeighbourVertices(t,e){let n=0;const i=this.edges,r=i.length;for(let s=0;s<r;s++){const r=i[s].getOtherVertex(this);t[e+n]=r,n++}return n}}ct.prototype.isTopoVertex=!0;class dt{constructor(){this.vertices=[],this.__edges=new Set,this.__faces=new Set}get byteSize(){let t=0;for(let e=0;e<this.vertices.length;e++)t+=this.vertices[e].byteSize;for(const e of this.__edges)t+=e.byteSize;for(const e of this.__faces)t+=e.byteSize;return t}getEdges(){return this.__edges}getFaces(){return this.__faces}getFaceByIndex(t){for(const e of this.__faces)if(e.index===t)return e}validate(t=tt){let e=!0,n="",i=0;function r(r){t(`${n}[${i}]: ${r}`),e=!1}n="Edge",i=0;const s=this.getEdges();for(let t of s){t.validate(r),this.containsVertex(t.v0)||r("Link to off-mesh vertex v0"),this.containsVertex(t.v1)||r("Link to off-mesh vertex v1");const e=t.faces,n=e.length;for(let t=0;t<n;t++){const n=e[t];this.containsFace(n)||r(`Link to off-mesh face[${t}]`)}i++}const o=this.getFaces();n="Face",i=0;for(let t of o){t.validate(r);const e=t.edges,n=e.length;for(let t=0;t<n;t++){const n=e[t];this.containsEdge(n)||r(`Link to off-mesh edge[${t}]`)}const s=t.vertices,o=s.length;for(let t=0;t<o;t++){const e=s[t];this.containsVertex(e)||r(`Link to off-mesh vertex[${t}]`)}i++}const a=this.vertices,h=a.length;n="Vertex";for(let t=0;t<h;t++){i=t;const e=a[t];e.validate(r);const n=e.edges,s=n.length;for(let t=0;t<s;t++){const e=n[t];this.containsEdge(e)||r(`Link to off-mesh edge[${t}]`)}const o=e.faces,h=o.length;for(let t=0;t<h;t++){const e=o[t];this.containsFace(e)||r(`Link to off-mesh face[${t}]`)}}return e}clone(){const t=new dt;return t.add(this),t}buildVertexMapping(){const t=new Map,e=this.vertices,n=e.length;for(let i=0;i<n;i++){const n=e[i];t.set(n.index,n)}return t}_addWithVertexMap(t,e){const n=t.getFaces();for(let t of n)this.addFaceCopy(t,e)}addFaceCopy(t,e){const n=new ht;X(n.normal,t.normal);const i=t.vertices;for(let t=0;t<3;t++){const r=i[t];let s=e.get(r.index);void 0===s&&(s=new ct,s.index=r.index,s.x=r.x,s.y=r.y,s.z=r.z,e.set(r.index,s),this.addVertex(s)),n.setVertexAt(t,s),s.addUniqueFace(n)}this.addFace(n),this.patchFaceEdges(n)}patchFaceEdges(t){const e=t.vertices,n=e[0],i=e[1],r=e[2],s=this.ensureEdge(n,i),o=this.ensureEdge(i,r),a=this.ensureEdge(r,n);s.addUniqueFace(t),o.addUniqueFace(t),a.addUniqueFace(t),t.addUniqueEdge(s),t.addUniqueEdge(o),t.addUniqueEdge(a)}add(t){const e=this.buildVertexMapping();this._addWithVertexMap(t,e)}addVertex(t){this.vertices.push(t)}addUniqueVertex(t){Z(this.vertices,t)}removeVertex(t){var e;e=t,it(this.vertices,e)}containsVertex(t){return-1!==this.vertices.indexOf(t)}addEdge(t){this.__edges.add(t)}addUniqueEdge(t){this.__edges.add(t)}removeEdge(t){var e;e=t,this.__edges.delete(e)}containsEdge(t){return this.__edges.has(t)}addFace(t){this.__faces.add(t)}injectManyFaces(t){for(let e of t)this.injectFace(e)}injectFace(t){this.addFace(t);const e=t.edges,n=e.length;for(let t=0;t<n;t++){const n=e[t];this.addUniqueEdge(n)}const i=t.vertices,r=i.length;for(let t=0;t<r;t++){const e=i[t];this.addUniqueVertex(e)}}removeFace(t){var e;e=t,this.__faces.delete(e)}containsFace(t){return this.__faces.has(t)}ensureEdge(t,e){const n=t.edges,i=n.length;for(let r=0;r<i;r++){const i=n[r];if(nt(i,t)===e)return i}const r=new st;return r.v0=t,r.v1=e,t.edges.push(r),e.edges.push(r),this.__edges.add(r),r}mergeEdges(){const t=this.getEdges();for(let e of t){const n=e.v0,i=e.v1;for(let r of t){if(e===r)continue;const t=r.v0,s=r.v1;if(n===t){if(i!==s)continue}else{if(n!==s)continue;if(i!==t)continue}this.removeEdge(r),e.merge(r)}}}computeEdgeSquaredLengths(){const t=this.getEdges();for(let e of t)e.computeSquaredLength()}build(t,e){const n=e.length,i=t.length/3,r=this.vertices;for(let e=0;e<i;e++){const n=3*e,i=new ct;i.index=e,i.x=t[n],i.y=t[n+1],i.z=t[n+2],r[e]=i}const s=n/3,o=this.getFaces();for(let t=0;t<s;t++){const n=3*t,i=e[n],s=e[n+1],a=e[n+2],h=r[i],c=r[s],d=r[a],u=new ht;u.index=t;const l=this.ensureEdge(h,c),f=this.ensureEdge(c,d),g=this.ensureEdge(d,h);l.faces.push(u),f.faces.push(u),g.faces.push(u),u.vertices.push(h,c,d),u.edges.push(l,f,g),h.faces.push(u),c.faces.push(u),d.faces.push(u),o.add(u)}}toString(){return`TopoMesh{ vertices: ${et(this.vertices.length)}, edges: ${et(this.getEdges().size)}, faces: ${et(this.getFaces().size)} }`}}dt.prototype.isTopoMesh=!0,self.Lib={build_bvh(t,e){const n=new x;return function(t,e,n){const i=n.length/3;t.setLeafCount(i),t.initialize_structure();for(let r=0;r<i;r++){const i=3*r;b(t,r,e,n[i],n[i+1],n[i+2])}t.build()}(n,t,e),n},Sampler2D:D,BufferedGeometryArraysBuilder:Y,tensionOptimizeUV:function(t,e,n,i){const r=new dt;r.build(t,n),r.computeEdgeSquaredLengths();const s=t.length/3;for(let t=0;t<i;t++)t:for(let t=0;t<s;t++){const n=r.vertices[t],i=n.edges,s=i.length;if(0===s)continue;let o=0,a=0,h=0;for(let t=0;t<s;t++){const r=i[t];if(r.isTopologyBorder())continue t;const s=2*r.getOtherVertex(n).index,c=e[s],d=e[s+1],u=1/r.lengthSqr;o+=c*u,a+=d*u,h+=u}const c=o/h,d=a/h,u=2*n.index;e[u]=c,e[u+1]=d}},sampler2d_channel_compute_min:function(t,e=0){const n=t.itemSize,i=t.data,r=i.length;if(0===r)return;let s=i[e],o=e;for(let t=e+n;t<r;t+=n){const e=i[t];s>e&&(s=e,o=t)}const a=t.width,h=o/n|0;return{index:o,value:s,x:h%a,y:h/a|0}},sampler2d_channel_compute_max:function(t,e=0){const n=t.itemSize,i=t.data,r=i.length;if(0===r)return;let s=i[e],o=e;for(let t=e+n;t<r;t+=n){const e=i[t];s<e&&(s=e,o=t)}const a=t.width,h=o/n|0;return{index:o,value:s,x:h%a,y:h/a|0}}};
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "description": "Fully featured ECS game engine written in JavaScript",
6
6
  "type": "module",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.111.3",
8
+ "version": "2.111.5",
9
9
  "main": "build/meep.module.js",
10
10
  "module": "build/meep.module.js",
11
11
  "exports": {
@@ -26,20 +26,20 @@ export class Cavity {
26
26
  private __boundary_size;
27
27
  /**
28
28
  * Add boundary information
29
- * @param vta
30
- * @param node1
31
- * @param node2
32
- * @param node3
33
- * @param bnd
29
+ * @param {number} vta
30
+ * @param {number} node1
31
+ * @param {number} node2
32
+ * @param {number} node3
33
+ * @param {number} bnd
34
34
  */
35
- push_boundary(vta: any, node1: any, node2: any, node3: any, bnd: any): void;
35
+ push_boundary(vta: number, node1: number, node2: number, node3: number, bnd: number): void;
36
36
  /**
37
37
  *
38
38
  * @param {number} i
39
39
  */
40
40
  push_deleted(i: number): void;
41
41
  /**
42
- *
42
+ * Primarily for debug
43
43
  * @param {number} i
44
44
  * @returns {boolean}
45
45
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Cavity.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/tetrahedra/delaunay/Cavity.js"],"names":[],"mappings":"AAEA;;GAEG;AACH;IAEQ;;;OAGG;IACH,WAFU,MAAM,EAAE,CAEC;IAEnB;;;OAGG;IACH,gBAFU,MAAM,CAEO;IAEvB;;;;OAIG;IACH,mBAAoB;IAEpB;;;;OAIG;IACH,wBAAwB;IAG5B;;;;;;;OAOG;IACH,4EAaC;IAED;;;OAGG;IACH,gBAFW,MAAM,QAMhB;IAED;;;;OAIG;IACH,YAHW,MAAM,GACJ,OAAO,CAYnB;IAED,cAGC;CACJ"}
1
+ {"version":3,"file":"Cavity.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/tetrahedra/delaunay/Cavity.js"],"names":[],"mappings":"AAEA;;GAEG;AACH;IACI;;;OAGG;IACH,WAFU,MAAM,EAAE,CAEH;IAEf;;;OAGG;IACH,gBAFU,MAAM,CAEG;IAEnB;;;;OAIG;IACH,mBAAgB;IAEhB;;;;OAIG;IACH,wBAAoB;IAEpB;;;;;;;OAOG;IACH,mBANW,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,OACN,MAAM,QAsBhB;IAED;;;OAGG;IACH,gBAFW,MAAM,QAMhB;IAED;;;;OAIG;IACH,YAHW,MAAM,GACJ,OAAO,CAYnB;IAED,cAGC;CACJ"}
@@ -4,55 +4,60 @@ import { assert } from "../../../../assert.js";
4
4
  * Represents cavity or "ball" formed when carving out "triangles" to accommodate inserted point
5
5
  */
6
6
  export class Cavity {
7
- constructor() {
8
- /**
9
- *
10
- * @type {number[]}
11
- */
12
- this.__deleted = [];
13
-
14
- /**
15
- *
16
- * @type {number}
17
- */
18
- this.__deleted_size = 0;
7
+ /**
8
+ *
9
+ * @type {number[]}
10
+ */
11
+ __deleted = [];
19
12
 
20
- /**
21
- * flat array of 5-tuples
22
- * @type {number[]}
23
- * @private
24
- */
25
- this.__boundary = [];
26
-
27
- /**
28
- *
29
- * @type {number}
30
- * @private
31
- */
32
- this.__boundary_size = 0;
33
- }
13
+ /**
14
+ *
15
+ * @type {number}
16
+ */
17
+ __deleted_size = 0;
18
+
19
+ /**
20
+ * flat array of 5-tuples
21
+ * @type {number[]}
22
+ * @private
23
+ */
24
+ __boundary = [];
25
+
26
+ /**
27
+ *
28
+ * @type {number}
29
+ * @private
30
+ */
31
+ __boundary_size = 0;
34
32
 
35
33
  /**
36
34
  * Add boundary information
37
- * @param vta
38
- * @param node1
39
- * @param node2
40
- * @param node3
41
- * @param bnd
35
+ * @param {number} vta
36
+ * @param {number} node1
37
+ * @param {number} node2
38
+ * @param {number} node3
39
+ * @param {number} bnd
42
40
  */
43
- push_boundary(vta, node1, node2, node3, bnd) {
41
+ push_boundary(
42
+ vta,
43
+ node1,
44
+ node2,
45
+ node3,
46
+ bnd
47
+ ) {
44
48
 
45
- const n = this.__boundary_size;
49
+ const n = this.__boundary_size++;
46
50
 
47
51
  const n5 = n * 5;
48
52
 
49
- this.__boundary[n5] = vta;
50
- this.__boundary[n5 + 1] = node1;
51
- this.__boundary[n5 + 2] = node2;
52
- this.__boundary[n5 + 3] = node3;
53
- this.__boundary[n5 + 4] = bnd;
53
+ const boundary = this.__boundary;
54
+
55
+ boundary[n5] = vta;
56
+ boundary[n5 + 1] = node1;
57
+ boundary[n5 + 2] = node2;
58
+ boundary[n5 + 3] = node3;
59
+ boundary[n5 + 4] = bnd;
54
60
 
55
- this.__boundary_size++;
56
61
  }
57
62
 
58
63
  /**
@@ -66,7 +71,7 @@ export class Cavity {
66
71
  }
67
72
 
68
73
  /**
69
- *
74
+ * Primarily for debug
70
75
  * @param {number} i
71
76
  * @returns {boolean}
72
77
  */
@@ -78,7 +78,7 @@ export function compute_delaunay_tetrahedral_mesh(mesh, input, n = input.length
78
78
 
79
79
  tetrahedral_mesh_compute_cavity(mesh, points, build_flags, CAVITY, current_tet, i);
80
80
 
81
- current_tet = fill_in_a_cavity(mesh, points, build_flags, CAVITY, current_tet);
81
+ current_tet = fill_in_a_cavity(mesh, points, build_flags, CAVITY);
82
82
 
83
83
  }
84
84
 
@@ -4,8 +4,7 @@
4
4
  * @param {ArrayLike<number>|number[]|Float32Array} points
5
5
  * @param {BitSet} visited_flags
6
6
  * @param {Cavity} cavity
7
- * @param {number} cur_tet
8
7
  * @returns {number} new current tet
9
8
  */
10
- export function fill_in_a_cavity(mesh: TetrahedralMesh, points: ArrayLike<number> | number[] | Float32Array, visited_flags: BitSet, cavity: Cavity, cur_tet: number): number;
9
+ export function fill_in_a_cavity(mesh: TetrahedralMesh, points: ArrayLike<number> | number[] | Float32Array, visited_flags: BitSet, cavity: Cavity): number;
11
10
  //# sourceMappingURL=fill_in_a_cavity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fill_in_a_cavity.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,gEANW,UAAU,MAAM,CAAC,GAAC,MAAM,EAAE,GAAC,YAAY,kDAGvC,MAAM,GACJ,MAAM,CAyElB"}
1
+ {"version":3,"file":"fill_in_a_cavity.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,gEALW,UAAU,MAAM,CAAC,GAAC,MAAM,EAAE,GAAC,YAAY,0CAGrC,MAAM,CAyElB"}
@@ -1,7 +1,6 @@
1
1
  import { assert } from "../../../../assert.js";
2
2
  import { array_copy } from "../../../../collection/array/array_copy.js";
3
3
  import { INVALID_NEIGHBOUR } from "../TetrahedralMesh.js";
4
- import { validate_neighbour } from "../validate_tetrahedral_mesh.js";
5
4
 
6
5
  /**
7
6
  *
@@ -9,10 +8,9 @@ import { validate_neighbour } from "../validate_tetrahedral_mesh.js";
9
8
  * @param {ArrayLike<number>|number[]|Float32Array} points
10
9
  * @param {BitSet} visited_flags
11
10
  * @param {Cavity} cavity
12
- * @param {number} cur_tet
13
11
  * @returns {number} new current tet
14
12
  */
15
- export function fill_in_a_cavity(mesh, points, visited_flags, cavity, cur_tet) {
13
+ export function fill_in_a_cavity(mesh, points, visited_flags, cavity) {
16
14
 
17
15
  let clength = cavity.__deleted_size; // cavity size
18
16
  const blength = cavity.__boundary_size; // boundary size
@@ -65,7 +63,7 @@ export function fill_in_a_cavity(mesh, points, visited_flags, cavity, cur_tet) {
65
63
  visited_flags.set(current_tet_index, false); // clear flag
66
64
  }
67
65
 
68
- computeAdjacencies(mesh, cavity, start, blength);
66
+ computeAdjecencies(mesh, cavity, start, blength);
69
67
 
70
68
 
71
69
  for (let i = 0; i < start; i++) {
@@ -85,29 +83,6 @@ export function fill_in_a_cavity(mesh, points, visited_flags, cavity, cur_tet) {
85
83
 
86
84
  }
87
85
 
88
- /**
89
- * All tets within the ball must be connected to one another, we test that here
90
- */
91
- function validate_patched_ball_adjacencies(mesh, ball_tets, ball_tets_offset, ball_tets_count, consumer) {
92
- let valid = true;
93
-
94
- let ball_index, tet;
95
-
96
- for (let i = 0; i < ball_tets_count; i++) {
97
- ball_index = ball_tets_offset + i;
98
- tet = ball_tets[ball_index];
99
-
100
- // except for 0th neighbour, all others must be valid as they represent connection within the ball itself
101
- for (let j = 1; j < 4; j++) {
102
-
103
- if (!validate_neighbour(mesh, tet, j, consumer)) {
104
- valid = false;
105
- }
106
- }
107
- }
108
-
109
- return valid;
110
- }
111
86
 
112
87
  /**
113
88
  * filling back the cavity
@@ -117,16 +92,16 @@ function validate_patched_ball_adjacencies(mesh, ball_tets, ball_tets_offset, ba
117
92
  * @param {TetrahedralMesh} mesh
118
93
  * @param {Cavity} cavity
119
94
  * @param {number} start
120
- * @param {number} blength
95
+ * @param {number} boundary_length
121
96
  */
122
- function computeAdjacencies(mesh, cavity, start, blength) {
97
+ function computeAdjecencies(mesh, cavity, start, boundary_length) {
123
98
  const boundary = cavity.__boundary;
124
99
 
125
100
  let tlength = 0;
126
101
 
127
102
  const Tmp = boundary; // we know there is enough space...
128
103
 
129
- for (let i = 0; i < blength; i++) {
104
+ for (let i = 0; i < boundary_length; i++) {
130
105
 
131
106
  const cur_tet = cavity.__deleted[start + i];
132
107
 
@@ -185,7 +160,7 @@ function computeAdjacencies(mesh, cavity, start, blength) {
185
160
 
186
161
  assert.equal(tlength, 0, 'Failed to compute adjacencies');
187
162
 
188
- // if (!validate_patched_ball_adjacencies(mesh, cavity.__deleted, start, blength, console.error)) {
163
+ // if (!validate_patched_ball_adjacencies(mesh, cavity.__deleted, start, boundary_length, console.error)) {
189
164
  // debugger;
190
165
  // }
191
166
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tetrahedral_mesh_build_from_grid.d.ts","sourceRoot":"","sources":["../../../../../../../../src/core/geom/3d/tetrahedra/delaunay/grid/tetrahedral_mesh_build_from_grid.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,gFAPW,MAAM,EAAE,gCAER,MAAM,iBACN,MAAM,iBACN,MAAM,GACJ,MAAM,CAgNlB"}
@@ -1,4 +1,5 @@
1
- import { assert } from "../../../../assert.js";
1
+ import { assert } from "../../../../../assert.js";
2
+
2
3
 
3
4
  /**
4
5
  * Special case of tetrahedral mesh generation using a regular 3d grid, useful for generating light probe volumes
@@ -24,7 +25,13 @@ export function tetrahedral_mesh_build_from_grid(
24
25
 
25
26
  mesh.clear();
26
27
 
27
- const tetrahedron_count = (resolution_x - 1) * (resolution_y - 1) * (resolution_z - 1) * 6;
28
+ const TETRAHEDRONS_PER_VOXEL = 6;
29
+
30
+ const voxel_resolution_x = resolution_x - 1;
31
+ const voxel_resolution_y = resolution_y - 1;
32
+ const voxel_resolution_z = resolution_z - 1;
33
+
34
+ const tetrahedron_count = voxel_resolution_x * voxel_resolution_y * voxel_resolution_z * TETRAHEDRONS_PER_VOXEL;
28
35
 
29
36
  // we know how many tetrahedrons will be created, so we can avoid some re-allocations by ensuring there's enough capacity
30
37
  mesh.ensureCapacity(tetrahedron_count);
@@ -45,9 +52,20 @@ export function tetrahedral_mesh_build_from_grid(
45
52
  return z * resolution_y * resolution_x + y * resolution_x + x;
46
53
  }
47
54
 
48
- function voxel_position_to_tetrahedral(x, y, z, index) {
55
+ /**
56
+ *
57
+ * @param {number} x
58
+ * @param {number} y
59
+ * @param {number} z
60
+ * @param {number} index
61
+ * @return {number}
62
+ */
63
+ function voxel_position_to_tetrahedral_index(x, y, z, index) {
64
+
65
+ const voxel_index = z * voxel_resolution_y * voxel_resolution_x + y * voxel_resolution_x + x;
66
+
67
+ return voxel_index * TETRAHEDRONS_PER_VOXEL + index;
49
68
 
50
- return (z * (resolution_y - 1) * (resolution_x - 1) + y * (resolution_x - 1) + x) * 6 + index;
51
69
  }
52
70
 
53
71
  // generate points
@@ -148,8 +166,8 @@ export function tetrahedral_mesh_build_from_grid(
148
166
 
149
167
  // prev x
150
168
  if (x > 1) {
151
- const tet_3_prev_x = voxel_position_to_tetrahedral(x - 2, y - 1, z - 1, 3);// prev x orange
152
- const tet_4_prev_x = voxel_position_to_tetrahedral(x - 2, y - 1, z - 1, 4); // prev x yellow
169
+ const tet_3_prev_x = voxel_position_to_tetrahedral_index(x - 2, y - 1, z - 1, 3);// prev x orange
170
+ const tet_4_prev_x = voxel_position_to_tetrahedral_index(x - 2, y - 1, z - 1, 4); // prev x yellow
153
171
 
154
172
  // blue
155
173
  mesh.setNeighbour(tet_1, 2, (tet_3_prev_x << 2) | 1); // H - prev x orange B
@@ -164,8 +182,8 @@ export function tetrahedral_mesh_build_from_grid(
164
182
 
165
183
  // prev y
166
184
  if (y > 1) {
167
- const tet_2_prev_y = voxel_position_to_tetrahedral(x - 1, y - 2, z - 1, 2); // prev y red
168
- const tet_5_prev_y = voxel_position_to_tetrahedral(x - 1, y - 2, z - 1, 5); // prev y green
185
+ const tet_2_prev_y = voxel_position_to_tetrahedral_index(x - 1, y - 2, z - 1, 2); // prev y red
186
+ const tet_5_prev_y = voxel_position_to_tetrahedral_index(x - 1, y - 2, z - 1, 5); // prev y green
169
187
 
170
188
  // purple
171
189
  mesh.setNeighbour(tet_0, 3, (tet_2_prev_y << 2) | 1); // H - prev y red B
@@ -179,8 +197,8 @@ export function tetrahedral_mesh_build_from_grid(
179
197
  }
180
198
 
181
199
  if (z > 1) {
182
- const tet_4_prev_z = voxel_position_to_tetrahedral(x - 1, y - 1, z - 2, 4); // prev z yellow
183
- const tet_5_prev_z = voxel_position_to_tetrahedral(x - 1, y - 1, z - 2, 5); // prev z green
200
+ const tet_4_prev_z = voxel_position_to_tetrahedral_index(x - 1, y - 1, z - 2, 4); // prev z yellow
201
+ const tet_5_prev_z = voxel_position_to_tetrahedral_index(x - 1, y - 1, z - 2, 5); // prev z green
184
202
 
185
203
  // purple
186
204
  mesh.setNeighbour(tet_0, 0, (tet_4_prev_z << 2) | 2); // B - prev z yellow H
@@ -1 +1 @@
1
- {"version":3,"file":"tetrahedral_mesh_compute_sub_determinant.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_sub_determinant.js"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,iEANW,MAAM,EAAE,GAAC,YAAY,iBACrB,MAAM,iCAEN,MAAM,EAAE,GAAC,YAAY,qBACrB,MAAM,QAoEhB"}
1
+ {"version":3,"file":"tetrahedral_mesh_compute_sub_determinant.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_sub_determinant.js"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,iEANW,MAAM,EAAE,GAAC,YAAY,iBACrB,MAAM,iCAEN,MAAM,EAAE,GAAC,YAAY,qBACrB,MAAM,QA2EhB"}
@@ -8,7 +8,14 @@
8
8
  * @param {number[]|Float32Array} points
9
9
  * @param {number} tetrahedron_index
10
10
  */
11
- export function tetrahedral_mesh_compute_sub_determinant(result, result_offset, mesh, points, tetrahedron_index) {
11
+ export function tetrahedral_mesh_compute_sub_determinant(
12
+ result,
13
+ result_offset,
14
+ mesh,
15
+ points,
16
+ tetrahedron_index
17
+ ) {
18
+
12
19
  /*
13
20
  NOTE: the code is re-ordered slightly and inlined for speed, re-ordering is mostly to reduce register pressure
14
21
  */
@@ -15,7 +15,7 @@ import { AABB3 } from "../aabb/AABB3.js";
15
15
  import { make_justified_point_grid } from "../util/make_justified_point_grid.js";
16
16
  import { build_tetrahedral_mesh_buffer_geometry } from "./build_tetrahedral_mesh_buffer_geometry.js";
17
17
  import { compute_delaunay_tetrahedral_mesh } from "./delaunay/compute_delaunay_tetrahedral_mesh.js";
18
- import { tetrahedral_mesh_build_from_grid } from "./delaunay/tetrahedral_mesh_build_from_grid.js";
18
+ import { tetrahedral_mesh_build_from_grid } from "./delaunay/grid/tetrahedral_mesh_build_from_grid.js";
19
19
  import { TetrahedralMesh } from "./TetrahedralMesh.js";
20
20
 
21
21
 
@@ -1 +1 @@
1
- {"version":3,"file":"validate_tetrahedral_mesh.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/tetrahedra/validate_tetrahedral_mesh.js"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,+DALW,MAAM,gBACN,MAAM,mBACG,MAAM,WACd,OAAO,CA6DlB;AAGD;;;;;GAKG;AACH,+EAHW,MAAM,mCAehB;AA0BD;;;;;;GAMG;AACH,yEAJW,UAAU,MAAM,CAAC,GAAC,MAAM,EAAE,GAAC,YAAY,2BAErC,OAAO,CAkCnB;qBA9JoB,2BAA2B"}
1
+ {"version":3,"file":"validate_tetrahedral_mesh.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/tetrahedra/validate_tetrahedral_mesh.js"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,+DALW,MAAM,gBACN,MAAM,mBACG,MAAM,WACd,OAAO,CA6DlB;AAGD;;;;;GAKG;AACH,+EAHW,MAAM,mCA0ChB;AA0BD;;;;;;GAMG;AACH,yEAJW,UAAU,MAAM,CAAC,GAAC,MAAM,EAAE,GAAC,YAAY,2BAErC,OAAO,CAkCnB;qBAzLoB,2BAA2B"}
@@ -90,6 +90,33 @@ export function validate_tetrahedron_neighbourhood(mesh, tet, consumer = noop) {
90
90
 
91
91
  }
92
92
 
93
+ // validate all neighbours together
94
+ for (let i = 0; i < 3; i++) {
95
+ const neighbour_a = mesh.getNeighbour(tet, i);
96
+
97
+ if (neighbour_a === INVALID_NEIGHBOUR) {
98
+ continue;
99
+ }
100
+
101
+ const tet_a = neighbour_a >>> 2;
102
+
103
+ for (let j = i+1; j < 4; j++) {
104
+ const neighbour_b = mesh.getNeighbour(tet, j);
105
+
106
+ if (neighbour_b === INVALID_NEIGHBOUR) {
107
+ continue;
108
+ }
109
+
110
+ const tet_b = neighbour_b >>> 2;
111
+
112
+ if (tet_a === tet_b) {
113
+ consumer(`Tetrahedron ${tet} points to the same neighbour tetrahedron ${tet_a} for neighbour index ${i} and ${j}. Each neighbour tet must be unique`)
114
+
115
+ valid = false;
116
+ }
117
+ }
118
+ }
119
+
93
120
  return valid;
94
121
  }
95
122
 
@@ -40,10 +40,10 @@ export class TopoMesh {
40
40
  getFaceByIndex(index: number): undefined | TopoTriangle;
41
41
  /**
42
42
  *
43
- * @param {function(reason:string)} error_consumer
43
+ * @param {function(reason:string)} [error_consumer]
44
44
  * @returns {boolean}
45
45
  */
46
- validate(error_consumer: any): boolean;
46
+ validate(error_consumer?: typeof noop): boolean;
47
47
  clone(): TopoMesh;
48
48
  /**
49
49
  *
@@ -62,6 +62,12 @@ export class TopoMesh {
62
62
  * @param {Map<number,TopoVertex>} vertex_map
63
63
  */
64
64
  addFaceCopy(face: TopoTriangle, vertex_map: Map<number, TopoVertex>): void;
65
+ /**
66
+ * Ensures that face has correct edges.
67
+ * NOTE: this method is additive, it will not *NOT* remove any references
68
+ * @param {TopoTriangle} face
69
+ */
70
+ patchFaceEdges(face: TopoTriangle): void;
65
71
  /**
66
72
  *
67
73
  * @param {TopoMesh} other
@@ -161,4 +167,5 @@ export class TopoMesh {
161
167
  import { TopoVertex } from "./TopoVertex.js";
162
168
  import { TopoEdge } from "./TopoEdge.js";
163
169
  import { TopoTriangle } from "./TopoTriangle.js";
170
+ import { noop } from "../../../../function/noop.js";
164
171
  //# sourceMappingURL=TopoMesh.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TopoMesh.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/topology/struct/TopoMesh.js"],"names":[],"mappings":"AAaA;IAGQ;;;OAGG;IACH,UAFU,UAAU,EAAE,CAEJ;IAElB;;;;OAIG;IACH,gBAAwB;IAGxB;;;;OAIG;IACH,gBAAwB;IAG5B;;;;OAIG;IACH,uBAkBC;IAED;;;OAGG;IACH,YAFa,IAAI,QAAQ,CAAC,CAIzB;IAED;;;OAGG;IACH,YAFa,IAAI,YAAY,CAAC,CAI7B;IAED;;;;OAIG;IACH,sBAHW,MAAM,GACL,SAAS,GAAC,YAAY,CAYjC;IAED;;;;OAIG;IACH,+BAFa,OAAO,CA0GnB;IAED,kBAMC;IAED;;;OAGG;IACH,sBAFa,IAAI,MAAM,EAAE,UAAU,CAAC,CAoBnC;IAED;;;;OAIG;IACH,yBAHW,QAAQ,cACR,IAAI,MAAM,EAAE,UAAU,CAAC,QAYjC;IAED;;;;OAIG;IACH,kBAHW,YAAY,cACZ,IAAI,MAAM,EAAC,UAAU,CAAC,QAuDhC;IAED;;;OAGG;IACH,WAFW,QAAQ,QAclB;IAED;;;OAGG;IACH,aAFW,UAAU,QAKpB;IAED;;;OAGG;IACH,mBAFW,UAAU,QAMpB;IAED;;;OAGG;IACH,gBAFW,UAAU,QAIpB;IAED;;;;OAIG;IACH,kBAHW,UAAU,GACR,OAAO,CAKnB;IAGD;;;OAGG;IACH,WAFW,QAAQ,QAKlB;IAED;;;OAGG;IACH,iBAFW,QAAQ,QAMlB;IAED;;;OAGG;IACH,cAFW,QAAQ,QAIlB;IAED;;;;OAIG;IACH,gBAHW,QAAQ,GACN,OAAO,CAKnB;IAED;;;OAGG;IACH,WAFW,YAAY,QAUtB;IAED;;;OAGG;IACH,uBAFW,SAAS,YAAY,CAAC,QAMhC;IAED;;;OAGG;IACH,cAFW,YAAY,QAwBtB;IAED;;;OAGG;IACH,cAFW,YAAY,QAItB;IAED;;;;OAIG;IACH,gBAHW,YAAY,GACV,OAAO,CAKnB;IAED;;;;;;OAMG;IACH,cALW,UAAU,KACV,UAAU,GAER,QAAQ,CAoCpB;IAED,mBAsCC;IAED,kCAQC;IAED;;;;OAIG;IACH,gBAHW,YAAY,SACZ,WAAW,GAAC,WAAW,GAAC,UAAU,GAAC,MAAM,EAAE,QAoErD;IAED,mBAEC;IAIL;;;OAGG;IACH,qBAFU,OAAO,CAEY;CAP5B;2BAroB0B,iBAAiB;yBAFnB,eAAe;6BACX,mBAAmB"}
1
+ {"version":3,"file":"TopoMesh.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/topology/struct/TopoMesh.js"],"names":[],"mappings":"AAcA;IAGQ;;;OAGG;IACH,UAFU,UAAU,EAAE,CAEJ;IAElB;;;;OAIG;IACH,gBAAwB;IAGxB;;;;OAIG;IACH,gBAAwB;IAG5B;;;;OAIG;IACH,uBAkBC;IAED;;;OAGG;IACH,YAFa,IAAI,QAAQ,CAAC,CAIzB;IAED;;;OAGG;IACH,YAFa,IAAI,YAAY,CAAC,CAI7B;IAED;;;;OAIG;IACH,sBAHW,MAAM,GACL,SAAS,GAAC,YAAY,CAYjC;IAED;;;;OAIG;IACH,wCAFa,OAAO,CA0GnB;IAED,kBAMC;IAED;;;OAGG;IACH,sBAFa,IAAI,MAAM,EAAE,UAAU,CAAC,CAoBnC;IAED;;;;OAIG;IACH,yBAHW,QAAQ,cACR,IAAI,MAAM,EAAE,UAAU,CAAC,QAYjC;IAED;;;;OAIG;IACH,kBAHW,YAAY,cACZ,IAAI,MAAM,EAAC,UAAU,CAAC,QAqChC;IAED;;;;OAIG;IACH,qBAFW,YAAY,QAsBtB;IAED;;;OAGG;IACH,WAFW,QAAQ,QAclB;IAED;;;OAGG;IACH,aAFW,UAAU,QAKpB;IAED;;;OAGG;IACH,mBAFW,UAAU,QAMpB;IAED;;;OAGG;IACH,gBAFW,UAAU,QAIpB;IAED;;;;OAIG;IACH,kBAHW,UAAU,GACR,OAAO,CAKnB;IAGD;;;OAGG;IACH,WAFW,QAAQ,QAKlB;IAED;;;OAGG;IACH,iBAFW,QAAQ,QAMlB;IAED;;;OAGG;IACH,cAFW,QAAQ,QAIlB;IAED;;;;OAIG;IACH,gBAHW,QAAQ,GACN,OAAO,CAKnB;IAED;;;OAGG;IACH,WAFW,YAAY,QAUtB;IAED;;;OAGG;IACH,uBAFW,SAAS,YAAY,CAAC,QAMhC;IAED;;;OAGG;IACH,cAFW,YAAY,QAwBtB;IAED;;;OAGG;IACH,cAFW,YAAY,QAItB;IAED;;;;OAIG;IACH,gBAHW,YAAY,GACV,OAAO,CAKnB;IAED;;;;;;OAMG;IACH,cALW,UAAU,KACV,UAAU,GAER,QAAQ,CAoCpB;IAED,mBAsCC;IAED,kCAQC;IAED;;;;OAIG;IACH,gBAHW,YAAY,SACZ,WAAW,GAAC,WAAW,GAAC,UAAU,GAAC,MAAM,EAAE,QAoErD;IAED,mBAEC;IAIL;;;OAGG;IACH,qBAFU,OAAO,CAEY;CAP5B;2BAtoB0B,iBAAiB;yBAFnB,eAAe;6BACX,mBAAmB;qBAR3B,8BAA8B"}
@@ -1,15 +1,16 @@
1
+ import { vec3 } from "gl-matrix";
1
2
  import { assert } from "../../../../assert.js";
2
- import { TopoEdge } from "./TopoEdge.js";
3
- import { TopoTriangle } from "./TopoTriangle.js";
4
- import { TopoVertex } from "./TopoVertex.js";
5
3
  import { array_push_if_unique } from "../../../../collection/array/array_push_if_unique.js";
6
- import { vec3 } from "gl-matrix";
7
- import { tm_kill_only_vert } from "../tm_kill_only_vert.js";
8
- import { tm_kill_only_edge } from "../tm_kill_only_edge.js";
9
- import { tm_kill_only_face } from "../tm_kill_only_face.js";
10
- import { query_edge_other_vertex } from "../query/query_edge_other_vertex.js";
4
+ import { noop } from "../../../../function/noop.js";
11
5
 
12
6
  import { number_format_by_thousands } from "../../../../primitives/numbers/number_format_by_thousands.js";
7
+ import { query_edge_other_vertex } from "../query/query_edge_other_vertex.js";
8
+ import { tm_kill_only_edge } from "../tm_kill_only_edge.js";
9
+ import { tm_kill_only_face } from "../tm_kill_only_face.js";
10
+ import { tm_kill_only_vert } from "../tm_kill_only_vert.js";
11
+ import { TopoEdge } from "./TopoEdge.js";
12
+ import { TopoTriangle } from "./TopoTriangle.js";
13
+ import { TopoVertex } from "./TopoVertex.js";
13
14
 
14
15
  export class TopoMesh {
15
16
  constructor() {
@@ -96,10 +97,10 @@ export class TopoMesh {
96
97
 
97
98
  /**
98
99
  *
99
- * @param {function(reason:string)} error_consumer
100
+ * @param {function(reason:string)} [error_consumer]
100
101
  * @returns {boolean}
101
102
  */
102
- validate(error_consumer) {
103
+ validate(error_consumer = noop) {
103
104
  let valid = true;
104
105
 
105
106
  let error_context = "";
@@ -293,8 +294,17 @@ export class TopoMesh {
293
294
  }
294
295
 
295
296
  this.addFace(f);
297
+ this.patchFaceEdges(f);
298
+ }
299
+
300
+ /**
301
+ * Ensures that face has correct edges.
302
+ * NOTE: this method is additive, it will not *NOT* remove any references
303
+ * @param {TopoTriangle} face
304
+ */
305
+ patchFaceEdges(face) {
296
306
 
297
- const f_vertices = f.vertices;
307
+ const f_vertices = face.vertices;
298
308
 
299
309
  const vA = f_vertices[0];
300
310
  const vB = f_vertices[1];
@@ -305,13 +315,13 @@ export class TopoMesh {
305
315
  const edge1 = this.ensureEdge(vB, vC);
306
316
  const edge2 = this.ensureEdge(vC, vA);
307
317
 
308
- edge0.addUniqueFace(f);
309
- edge1.addUniqueFace(f);
310
- edge2.addUniqueFace(f);
318
+ edge0.addUniqueFace(face);
319
+ edge1.addUniqueFace(face);
320
+ edge2.addUniqueFace(face);
311
321
 
312
- f.addUniqueEdge(edge0);
313
- f.addUniqueEdge(edge1);
314
- f.addUniqueEdge(edge2);
322
+ face.addUniqueEdge(edge0);
323
+ face.addUniqueEdge(edge1);
324
+ face.addUniqueEdge(edge2);
315
325
  }
316
326
 
317
327
  /**
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Adds input to output
3
3
  * `out += input`
4
- * @param {number[]} out
4
+ * @param {number[]|Float32Array|Float64Array} out
5
5
  * @param {number} out_offset
6
- * @param {number[]} input
6
+ * @param {number[]|Float32Array|Float64Array} input
7
7
  * @param {number} input_offset
8
8
  */
9
- export function v3_array_immediate_add(out: number[], out_offset: number, input: number[], input_offset: number): void;
9
+ export function v3_array_immediate_add(out: number[] | Float32Array | Float64Array, out_offset: number, input: number[] | Float32Array | Float64Array, input_offset: number): void;
10
10
  //# sourceMappingURL=v3_array_immediate_add.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"v3_array_immediate_add.d.ts","sourceRoot":"","sources":["../../../../../src/core/geom/vec3/v3_array_immediate_add.js"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,4CALW,MAAM,EAAE,cACR,MAAM,SACN,MAAM,EAAE,gBACR,MAAM,QAYhB"}
1
+ {"version":3,"file":"v3_array_immediate_add.d.ts","sourceRoot":"","sources":["../../../../../src/core/geom/vec3/v3_array_immediate_add.js"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,4CALW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,cAClC,MAAM,SACN,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,gBAClC,MAAM,QAYhB"}
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Adds input to output
3
3
  * `out += input`
4
- * @param {number[]|Float32Array} out
4
+ * @param {number[]|Float32Array|Float64Array} out
5
5
  * @param {number} out_offset
6
- * @param {number[]} input
6
+ * @param {number[]|Float32Array|Float64Array} input
7
7
  * @param {number} input_offset
8
8
  */
9
9
  export function v3_array_immediate_add(out, out_offset, input, input_offset) {
@@ -1 +1 @@
1
- {"version":3,"file":"BufferedGeometryArraysBuilder.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/terrain/BufferedGeometryArraysBuilder.js"],"names":[],"mappings":";;;;AAEA;;;;;;;;;GASG;AACH,iJAHW,MAAM;;cACgB,YAAY;aAAW,YAAY;SAAO,YAAY;EAwGtF"}
1
+ {"version":3,"file":"BufferedGeometryArraysBuilder.d.ts","sourceRoot":"","sources":["../../../../../src/engine/ecs/terrain/BufferedGeometryArraysBuilder.js"],"names":[],"mappings":";;;;AAIA;;;;;;;;;GASG;AACH,iJAHW,MAAM;;cACgB,YAAY;aAAW,YAAY;SAAO,YAAY;EAwGtF"}
@@ -1,4 +1,6 @@
1
- import { geometry_compute_vertex_normals } from '../../graphics/geometry/buffered/geometry_compute_vertex_normals.js';
1
+ import {
2
+ geometry_compute_vertex_normals_indexed
3
+ } from '../../graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.js';
2
4
 
3
5
  /**
4
6
  *
@@ -103,7 +105,7 @@ function buildBufferGeometry(samplerHeight, position, size, scale, totalSize, re
103
105
  }
104
106
  }
105
107
 
106
- geometry_compute_vertex_normals(vertices, normals, indices);
108
+ geometry_compute_vertex_normals_indexed(vertices, normals, indices);
107
109
 
108
110
  //CleanupGeometry(geometry);
109
111
  return {
@@ -0,0 +1,9 @@
1
+ /**
2
+ * based on code from THREE.js
3
+ * Prior to calling this function, normals need to be set to 0
4
+ * @param {Array.<number>|Float32Array} positions
5
+ * @param {Array.<number>|Float32Array} normals
6
+ * @param {Array.<number>|Uint32Array} indices
7
+ */
8
+ export function geometry_compute_vertex_normals_indexed(positions: Array<number> | Float32Array, normals: Array<number> | Float32Array, indices: Array<number> | Uint32Array): void;
9
+ //# sourceMappingURL=geometry_compute_vertex_normals_indexed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry_compute_vertex_normals_indexed.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_indexed.js"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,mEAJW,MAAO,MAAM,CAAC,GAAC,YAAY,WAC3B,MAAO,MAAM,CAAC,GAAC,YAAY,WAC3B,MAAO,MAAM,CAAC,GAAC,WAAW,QAgCpC"}
@@ -0,0 +1,45 @@
1
+ import { v3_array_immediate_add } from "../../../../core/geom/vec3/v3_array_immediate_add.js";
2
+ import { geometry_construct_triangle_normal } from "../geometry_construct_triangle_normal.js";
3
+ import { v3_array_normalize_many } from "./v3_array_normalize_many.js";
4
+
5
+ const scratch_v3 = new Float64Array(3);
6
+
7
+ /**
8
+ * based on code from THREE.js
9
+ * Prior to calling this function, normals need to be set to 0
10
+ * @param {Array.<number>|Float32Array} positions
11
+ * @param {Array.<number>|Float32Array} normals
12
+ * @param {Array.<number>|Uint32Array} indices
13
+ */
14
+ export function geometry_compute_vertex_normals_indexed(
15
+ positions,
16
+ normals,
17
+ indices
18
+ ) {
19
+
20
+ const index_length = indices.length;
21
+ for (let i = 0; i < index_length; i += 3) {
22
+
23
+ const a = indices[i];
24
+ const b = indices[i + 1];
25
+ const c = indices[i + 2];
26
+
27
+
28
+ geometry_construct_triangle_normal(
29
+ scratch_v3, 0,
30
+ a, b, c, positions
31
+ );
32
+
33
+ // accumulate
34
+
35
+ v3_array_immediate_add(normals, a * 3, scratch_v3, 0);
36
+ v3_array_immediate_add(normals, b * 3, scratch_v3, 0);
37
+ v3_array_immediate_add(normals, c * 3, scratch_v3, 0);
38
+
39
+ }
40
+
41
+ // restore unit magnitude
42
+
43
+ v3_array_normalize_many(normals);
44
+ }
45
+
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @param {Array.<number>|Float32Array} positions
3
+ * @param {Array.<number>|Float32Array} normals
4
+ * @param {number} vertex_count
5
+ */
6
+ export function geometry_compute_vertex_normals_unindexed(positions: Array<number> | Float32Array, normals: Array<number> | Float32Array, vertex_count: number): void;
7
+ //# sourceMappingURL=geometry_compute_vertex_normals_unindexed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry_compute_vertex_normals_unindexed.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals_unindexed.js"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,qEAJW,MAAO,MAAM,CAAC,GAAC,YAAY,WAC3B,MAAO,MAAM,CAAC,GAAC,YAAY,gBAC3B,MAAM,QAgChB"}
@@ -0,0 +1,42 @@
1
+ import { array_copy } from "../../../../core/collection/array/array_copy.js";
2
+ import { geometry_construct_triangle_normal } from "../geometry_construct_triangle_normal.js";
3
+ import { v3_array_normalize_many } from "./v3_array_normalize_many.js";
4
+
5
+ const scratch_v3 = new Float64Array(3);
6
+
7
+ /**
8
+ * @param {Array.<number>|Float32Array} positions
9
+ * @param {Array.<number>|Float32Array} normals
10
+ * @param {number} vertex_count
11
+ */
12
+ export function geometry_compute_vertex_normals_unindexed(
13
+ positions,
14
+ normals,
15
+ vertex_count
16
+ ) {
17
+
18
+ for (let i = 0; i < vertex_count; i += 3) {
19
+
20
+ // each sequential 3 vertices make up a unique triangle
21
+
22
+ const a = i;
23
+ const b = i + 1;
24
+ const c = i + 2;
25
+
26
+ geometry_construct_triangle_normal(
27
+ scratch_v3, 0,
28
+ a, b, c, positions
29
+ );
30
+
31
+ // accumulate
32
+
33
+ array_copy(scratch_v3, 0, normals, a * 3, 3);
34
+ array_copy(scratch_v3, 0, normals, b * 3, 3);
35
+ array_copy(scratch_v3, 0, normals, c * 3, 3);
36
+
37
+ }
38
+
39
+ // ensure unit magnitude
40
+
41
+ v3_array_normalize_many(normals);
42
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ *
3
+ * @param {number[]|Float32Array} input
4
+ * @param {number} [input_offset]
5
+ * @param {number} [input_length]
6
+ */
7
+ export function v3_array_normalize_many(input: number[] | Float32Array, input_offset?: number, input_length?: number): void;
8
+ //# sourceMappingURL=v3_array_normalize_many.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v3_array_normalize_many.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/geometry/buffered/v3_array_normalize_many.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,+CAJW,MAAM,EAAE,GAAC,YAAY,iBACrB,MAAM,iBACN,MAAM,QAehB"}
@@ -0,0 +1,22 @@
1
+ import { v3_array_normalize } from "../../../../core/geom/vec3/v3_array_normalize.js";
2
+
3
+ /**
4
+ *
5
+ * @param {number[]|Float32Array} input
6
+ * @param {number} [input_offset]
7
+ * @param {number} [input_length]
8
+ */
9
+ export function v3_array_normalize_many(
10
+ input,
11
+ input_offset = 0,
12
+ input_length = (input.length - input_offset)
13
+ ) {
14
+
15
+ const end = input_offset + input_length;
16
+
17
+ for (let i = input_offset; i < end; i += 3) {
18
+
19
+ v3_array_normalize(input, i, input, i);
20
+
21
+ }
22
+ }
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  *
3
- * @param {number[]|Float32Array} out
3
+ * @param {number[]|Float32Array|Float64Array} out
4
4
  * @param {number} out_offset
5
5
  * @param {number} a
6
6
  * @param {number} b
7
7
  * @param {number} c
8
8
  * @param {number[]|Float32Array} positions
9
9
  */
10
- export function geometry_construct_triangle_normal(out: number[] | Float32Array, out_offset: number, a: number, b: number, c: number, positions: number[] | Float32Array): void;
10
+ export function geometry_construct_triangle_normal(out: number[] | Float32Array | Float64Array, out_offset: number, a: number, b: number, c: number, positions: number[] | Float32Array): void;
11
11
  //# sourceMappingURL=geometry_construct_triangle_normal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"geometry_construct_triangle_normal.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics/geometry/geometry_construct_triangle_normal.js"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wDAPW,MAAM,EAAE,GAAC,YAAY,cACrB,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,aACN,MAAM,EAAE,GAAC,YAAY,QAqB/B"}
1
+ {"version":3,"file":"geometry_construct_triangle_normal.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics/geometry/geometry_construct_triangle_normal.js"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wDAPW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,cAClC,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,aACN,MAAM,EAAE,GAAC,YAAY,QAqB/B"}
@@ -2,7 +2,7 @@ import { v3_compute_triangle_normal } from "../../../core/geom/3d/v3_compute_tri
2
2
 
3
3
  /**
4
4
  *
5
- * @param {number[]|Float32Array} out
5
+ * @param {number[]|Float32Array|Float64Array} out
6
6
  * @param {number} out_offset
7
7
  * @param {number} a
8
8
  * @param {number} b
@@ -4,7 +4,7 @@ import {
4
4
  } from "../../../../core/geom/3d/tetrahedra/delaunay/compute_delaunay_tetrahedral_mesh.js";
5
5
  import {
6
6
  tetrahedral_mesh_build_from_grid
7
- } from "../../../../core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_build_from_grid.js";
7
+ } from "../../../../core/geom/3d/tetrahedra/delaunay/grid/tetrahedral_mesh_build_from_grid.js";
8
8
  import { TetrahedralMesh } from "../../../../core/geom/3d/tetrahedra/TetrahedralMesh.js";
9
9
  import { EntityNode } from "../../../ecs/parent/EntityNode.js";
10
10
  import { Transform } from "../../../ecs/transform/Transform.js";
@@ -1 +0,0 @@
1
- {"version":3,"file":"tetrahedral_mesh_build_from_grid.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_build_from_grid.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,gFAPW,MAAM,EAAE,gCAER,MAAM,iBACN,MAAM,iBACN,MAAM,GACJ,MAAM,CA+LlB"}
@@ -1,9 +0,0 @@
1
- /**
2
- * based on code from THREE.js
3
- * Prior to calling this function, normals need to be set to 0
4
- * @param {Array.<number>|Float32Array} positions
5
- * @param {Array.<number>|Float32Array} normals
6
- * @param {Array.<number>|Uint32Array} indices
7
- */
8
- export function geometry_compute_vertex_normals(positions: Array<number> | Float32Array, normals: Array<number> | Float32Array, indices: Array<number> | Uint32Array): void;
9
- //# sourceMappingURL=geometry_compute_vertex_normals.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"geometry_compute_vertex_normals.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/geometry/buffered/geometry_compute_vertex_normals.js"],"names":[],"mappings":"AAeA;;;;;;GAMG;AACH,2DAJW,MAAO,MAAM,CAAC,GAAC,YAAY,WAC3B,MAAO,MAAM,CAAC,GAAC,YAAY,WAC3B,MAAO,MAAM,CAAC,GAAC,WAAW,QAsEpC"}
@@ -1,91 +0,0 @@
1
- import { v3_array_normalize } from "../../../../core/geom/vec3/v3_array_normalize.js";
2
-
3
- /**
4
- *
5
- * @param {Array.<number>} normals
6
- */
7
- function normalizeVectors(normals) {
8
- const count = normals.length;
9
- for (let i = 0; i < count; i += 3) {
10
-
11
- v3_array_normalize(normals, i, normals, i);
12
-
13
- }
14
- }
15
-
16
- /**
17
- * based on code from THREE.js
18
- * Prior to calling this function, normals need to be set to 0
19
- * @param {Array.<number>|Float32Array} positions
20
- * @param {Array.<number>|Float32Array} normals
21
- * @param {Array.<number>|Uint32Array} indices
22
- */
23
- export function geometry_compute_vertex_normals(
24
- positions,
25
- normals,
26
- indices
27
- ) {
28
- let vA, vB, vC;
29
-
30
- let vAx, vAy, vAz, vBx, vBy, vBz, vCx, vCy, vCz;
31
-
32
- let vCBx, vCBy, vCBz, vABx, vABy, vABz;
33
-
34
- let crossX, crossY, crossZ;
35
- // indexed elements
36
-
37
- let i = 0;
38
-
39
- const index_length = indices.length;
40
- for (; i < index_length; i += 3) {
41
-
42
- vA = indices[i] * 3;
43
- vB = indices[i + 1] * 3;
44
- vC = indices[i + 2] * 3;
45
-
46
- //obtain vertex coordinates
47
- vAx = positions[vA];
48
- vAy = positions[vA + 1];
49
- vAz = positions[vA + 2];
50
-
51
- vBx = positions[vB];
52
- vBy = positions[vB + 1];
53
- vBz = positions[vB + 2];
54
-
55
- vCx = positions[vC];
56
- vCy = positions[vC + 1];
57
- vCz = positions[vC + 2];
58
-
59
- //compute CB and AB vectors
60
- vCBx = vCx - vBx;
61
- vCBy = vCy - vBy;
62
- vCBz = vCz - vBz;
63
-
64
- vABx = vAx - vBx;
65
- vABy = vAy - vBy;
66
- vABz = vAz - vBz;
67
-
68
- //compute triangle normal
69
- crossX = vCBy * vABz - vCBz * vABy;
70
- crossY = vCBz * vABx - vCBx * vABz;
71
- crossZ = vCBx * vABy - vCBy * vABx;
72
-
73
- // accumulate normal values
74
-
75
- normals[vA] += crossX;
76
- normals[vA + 1] += crossY;
77
- normals[vA + 2] += crossZ;
78
-
79
- normals[vB] += crossX;
80
- normals[vB + 1] += crossY;
81
- normals[vB + 2] += crossZ;
82
-
83
- normals[vC] += crossX;
84
- normals[vC + 1] += crossY;
85
- normals[vC + 2] += crossZ;
86
- }
87
-
88
- // restore unit magnitude
89
-
90
- normalizeVectors(normals);
91
- }