x_ite-sog-parser 1.1.2 → 1.2.0

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.
package/README.md CHANGED
@@ -13,18 +13,16 @@ Include the script after X_ITE:
13
13
 
14
14
  ```html
15
15
  <script defer src="https://cdn.jsdelivr.net/npm/x_ite@VERSION/dist/x_ite.min.js"></script>
16
- <script defer src="https://cdn.jsdelivr.net/npm/x_ite-sog-parser@1.1.2/dist/x_ite-sog-parser-2.min.js"></script>
16
+ <script defer src="https://cdn.jsdelivr.net/npm/x_ite-sog-parser@1.2.0/dist/x_ite-sog-parser-2.min.js"></script>
17
17
  <!-- or as ES module -->
18
18
  <script type="module" src="https://cdn.jsdelivr.net/npm/x_ite@VERSION/dist/x_ite.min.mjs"></script>
19
- <script type="module" src="https://cdn.jsdelivr.net/npm/x_ite-sog-parser@1.1.2/dist/x_ite-sog-parser-2.min.js"></script>
19
+ <script type="module" src="https://cdn.jsdelivr.net/npm/x_ite-sog-parser@1.2.0/dist/x_ite-sog-parser-2.min.js"></script>
20
20
  ```
21
21
 
22
- Now you can directly load `.sog` files with the `src` attribute, but you also have to add the `extensions` attribute with a number, how many X_ITE extension you have included. Each extension will decrease this count and when it becomes `0`, the canvas knows that all extensions are loaded and now starts loading the file in the `src` attribute.
23
-
24
- You can also use `.sog` files as source of an Inline node.
22
+ You can now load `.sog` files directly using the `src` attribute, but you can also use `.sog` files as source of an Inline node.
25
23
 
26
24
  ```html
27
- <x3d-canvas src="room.sog" extensions="1"></x3d-canvas>
25
+ <x3d-canvas src="room.sog"></x3d-canvas>
28
26
  ```
29
27
 
30
28
  ## NPM
@@ -2694,472 +2694,503 @@ function unzipSync(data, opts) {
2694
2694
  return files;
2695
2695
  }
2696
2696
 
2697
- ;// ./src/x_ite-sog-parser-2.js
2697
+ ;// ./node_modules/x_ite-extension/dist/x_ite-extension.js
2698
+ /******/ // The require scope
2699
+ /******/ var __nested_webpack_require_43__ = {};
2700
+ /******/
2701
+ /************************************************************************/
2702
+ /******/ /* webpack/runtime/define property getters */
2703
+ /******/ (() => {
2704
+ /******/ // define getter functions for harmony exports
2705
+ /******/ __nested_webpack_require_43__.d = (exports, definition) => {
2706
+ /******/ for(var key in definition) {
2707
+ /******/ if(__nested_webpack_require_43__.o(definition, key) && !__nested_webpack_require_43__.o(exports, key)) {
2708
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
2709
+ /******/ }
2710
+ /******/ }
2711
+ /******/ };
2712
+ /******/ })();
2713
+ /******/
2714
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
2715
+ /******/ (() => {
2716
+ /******/ __nested_webpack_require_43__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
2717
+ /******/ })();
2718
+ /******/
2719
+ /************************************************************************/
2720
+ var __nested_webpack_exports__ = {};
2721
+ /* harmony export */ __nested_webpack_require_43__.d(__nested_webpack_exports__, {
2722
+ /* harmony export */ A: () => (/* binding */ register)
2723
+ /* harmony export */ });
2724
+ function register (callback)
2725
+ {
2726
+ const X3D = window [Symbol .for ("X_ITE.X3D")];
2727
+
2728
+ if (X3D)
2729
+ callback (X3D);
2730
+ else
2731
+ (window [Symbol .for ("X_ITE.extensions")] ??= [ ]) .push (callback);
2732
+ };
2698
2733
 
2734
+ const __webpack_exports__default = __nested_webpack_exports__.A;
2699
2735
 
2700
- const X3D = window [Symbol .for ("X_ITE.X3D")];
2701
2736
 
2702
- /*
2703
- * Parser
2704
- * Reference: https://github.com/playcanvas/splat-transform/blob/main/src/lib/readers/read-sog.ts
2705
- */
2737
+ ;// ./src/x_ite-sog-parser-2.js
2706
2738
 
2707
- class SOGParser extends X3D .X3DParser
2739
+
2740
+
2741
+ __webpack_exports__default (X3D =>
2708
2742
  {
2709
- constructor (scene)
2710
- {
2711
- super (scene);
2712
- }
2743
+ /*
2744
+ * Parser
2745
+ * Reference: https://github.com/playcanvas/splat-transform/blob/main/src/lib/readers/read-sog.ts
2746
+ */
2713
2747
 
2714
- getEncoding ()
2748
+ class SOGParser extends X3D .X3DParser
2715
2749
  {
2716
- return "ARRAY_BUFFER";
2717
- }
2750
+ constructor (scene)
2751
+ {
2752
+ super (scene);
2753
+ }
2718
2754
 
2719
- setInput (buffer)
2720
- {
2721
- this .buffer = buffer;
2722
- }
2755
+ getEncoding ()
2756
+ {
2757
+ return "ARRAY_BUFFER";
2758
+ }
2723
2759
 
2724
- isValid ()
2725
- {
2726
- if (this .buffer .byteLength < 4)
2727
- return false;
2760
+ setInput (buffer)
2761
+ {
2762
+ this .buffer = buffer;
2763
+ }
2728
2764
 
2729
- // Check magic.
2765
+ isValid ()
2766
+ {
2767
+ if (this .buffer .byteLength < 4)
2768
+ return false;
2730
2769
 
2731
- const dataView = new DataView (this .buffer);
2770
+ // Check magic.
2732
2771
 
2733
- if (dataView .getUint32 (0, false) !== 0x504B0304)
2734
- return false;
2772
+ const dataView = new DataView (this .buffer);
2735
2773
 
2736
- // Check minimum requirement for Gaussian Splats.
2774
+ if (dataView .getUint32 (0, false) !== 0x504B0304)
2775
+ return false;
2737
2776
 
2738
- const keys = [
2739
- "means_l.webp",
2740
- "means_u.webp",
2741
- "scales.webp",
2742
- "sh0.webp",
2743
- "quats.webp",
2744
- "meta.json",
2745
- ];
2777
+ // Check minimum requirement for Gaussian Splats.
2746
2778
 
2747
- this .files = unzipSync (new Uint8Array (this .buffer));
2779
+ const keys = [
2780
+ "means_l.webp",
2781
+ "means_u.webp",
2782
+ "scales.webp",
2783
+ "sh0.webp",
2784
+ "quats.webp",
2785
+ "meta.json",
2786
+ ];
2748
2787
 
2749
- if (!keys .every (key => this .files [key]))
2750
- return false;
2788
+ this .files = unzipSync (new Uint8Array (this .buffer));
2751
2789
 
2752
- // Check version.
2790
+ if (!keys .every (key => this .files [key]))
2791
+ return false;
2753
2792
 
2754
- const meta = this .parseMeta ();
2793
+ // Check version.
2755
2794
 
2756
- if (meta .version < 2 || meta .version > 2)
2757
- return false;
2795
+ const meta = this .parseMeta ();
2758
2796
 
2759
- return true;
2760
- }
2797
+ if (meta .version < 2 || meta .version > 2)
2798
+ return false;
2761
2799
 
2762
- parseIntoScene (resolve, reject)
2763
- {
2764
- this .sog ()
2765
- .then (resolve)
2766
- .catch (reject);
2767
- }
2800
+ return true;
2801
+ }
2768
2802
 
2769
- async sog ()
2770
- {
2771
- const
2772
- browser = this .getBrowser (),
2773
- scene = this .getScene ();
2803
+ parseIntoScene (resolve, reject)
2804
+ {
2805
+ this .sog ()
2806
+ .then (resolve)
2807
+ .catch (reject);
2808
+ }
2774
2809
 
2775
- scene .setEncoding ("SOG");
2776
- scene .setProfile (browser .getProfile ("Interchange"));
2777
- scene .addComponent (browser .getComponent ("X_ITE"));
2810
+ async sog ()
2811
+ {
2812
+ const
2813
+ browser = this .getBrowser (),
2814
+ scene = this .getScene ();
2778
2815
 
2779
- await this .getBrowser () .loadComponents (scene);
2816
+ scene .setEncoding ("SOG");
2817
+ scene .setProfile (browser .getProfile ("Interchange"));
2818
+ scene .addComponent (browser .getComponent ("X_ITE"));
2780
2819
 
2781
- const
2782
- transform = scene .createNode ("Transform"),
2783
- gaussianSplats = scene .createNode ("GaussianSplats"),
2784
- gaussianCloud = await this .unpackFiles ();
2820
+ await this .getBrowser () .loadComponents (scene);
2785
2821
 
2786
- gaussianSplats .positions = gaussianCloud .positions;
2787
- gaussianSplats .orientations = gaussianCloud .rotations;
2788
- gaussianSplats .scales = gaussianCloud .scales;
2789
- gaussianSplats .opacities = gaussianCloud .alphas;
2822
+ const
2823
+ transform = scene .createNode ("Transform"),
2824
+ gaussianSplats = scene .createNode ("GaussianSplats"),
2825
+ gaussianCloud = await this .unpackFiles ();
2790
2826
 
2791
- gaussianSplats .sphericalHarmonicsDegree0Coef0 = gaussianCloud .colors;
2827
+ gaussianSplats .positions = gaussianCloud .positions;
2828
+ gaussianSplats .orientations = gaussianCloud .rotations;
2829
+ gaussianSplats .scales = gaussianCloud .scales;
2830
+ gaussianSplats .opacities = gaussianCloud .alphas;
2792
2831
 
2793
- // Set spherical harmonics.
2832
+ gaussianSplats .sphericalHarmonicsDegree0Coef0 = gaussianCloud .colors;
2794
2833
 
2795
- if (gaussianCloud .shs .length)
2796
- {
2797
- const {
2798
- meta: { count, shN: { bands } },
2799
- } = this .files;
2834
+ // Set spherical harmonics.
2800
2835
 
2801
- const
2802
- shs = gaussianCloud .shs,
2803
- shDegree = bands;
2836
+ if (gaussianCloud .shs .length)
2837
+ {
2838
+ const {
2839
+ meta: { count, shN: { bands } },
2840
+ } = this .files;
2804
2841
 
2805
- this .setSphericalHarmonics (count, shs, shDegree, gaussianSplats)
2806
- }
2842
+ const
2843
+ shs = gaussianCloud .shs,
2844
+ shDegree = bands;
2807
2845
 
2808
- // Add nodes to scene.
2846
+ this .setSphericalHarmonics (count, shs, shDegree, gaussianSplats)
2847
+ }
2809
2848
 
2810
- transform .rotation = new X3D .Rotation4 (1, 0, 0, Math .PI);
2849
+ // Add nodes to scene.
2811
2850
 
2812
- transform .children .push (gaussianSplats);
2813
- scene .rootNodes .push (transform);
2851
+ transform .rotation = new X3D .Rotation4 (1, 0, 0, Math .PI);
2814
2852
 
2815
- return scene;
2816
- }
2853
+ transform .children .push (gaussianSplats);
2854
+ scene .rootNodes .push (transform);
2817
2855
 
2818
- setSphericalHarmonics (numSplats, shs, shDegree, gaussianSplats)
2819
- {
2820
- const
2821
- shCoeffs = this .dimForDegree (shDegree),
2822
- shCoeffs3 = this .dimForDegree (shDegree) * 3,
2823
- splatShs = Array .from ({ length: shCoeffs }, () => [ ]);
2856
+ return scene;
2857
+ }
2824
2858
 
2825
- for (let c = 0; c < shCoeffs; ++ c)
2859
+ setSphericalHarmonics (numSplats, shs, shDegree, gaussianSplats)
2826
2860
  {
2827
2861
  const
2828
- c3 = c * 3,
2829
- splatSh = splatShs [c];
2862
+ shCoeffs = this .dimForDegree (shDegree),
2863
+ shCoeffs3 = this .dimForDegree (shDegree) * 3,
2864
+ splatShs = Array .from ({ length: shCoeffs }, () => [ ]);
2830
2865
 
2831
- for (let i = 0; i < numSplats; ++ i)
2866
+ for (let c = 0; c < shCoeffs; ++ c)
2832
2867
  {
2833
- const offset = shCoeffs3 * i + c3;
2868
+ const
2869
+ c3 = c * 3,
2870
+ splatSh = splatShs [c];
2871
+
2872
+ for (let i = 0; i < numSplats; ++ i)
2873
+ {
2874
+ const offset = shCoeffs3 * i + c3;
2834
2875
 
2835
- for (let j = 0; j < 3; ++ j)
2836
- splatSh .push (shs [offset + j]);
2876
+ for (let j = 0; j < 3; ++ j)
2877
+ splatSh .push (shs [offset + j]);
2878
+ }
2837
2879
  }
2838
- }
2839
2880
 
2840
- // GaussianSplats node only supports up to degree 3.
2841
- const shDegreeMax = Math .min (shDegree, 3);
2881
+ // GaussianSplats node only supports up to degree 3.
2882
+ const shDegreeMax = Math .min (shDegree, 3);
2842
2883
 
2843
- for (let d = 0, i = 0; d < shDegreeMax; ++ d)
2844
- {
2845
- const coefs = this .coefsForDegree (d);
2884
+ for (let d = 0, i = 0; d < shDegreeMax; ++ d)
2885
+ {
2886
+ const coefs = this .coefsForDegree (d);
2846
2887
 
2847
- for (let c = 0; c < coefs; ++ c, ++ i)
2848
- gaussianSplats [`sphericalHarmonicsDegree${d + 1}Coef${c}`] = splatShs [i];
2888
+ for (let c = 0; c < coefs; ++ c, ++ i)
2889
+ gaussianSplats [`sphericalHarmonicsDegree${d + 1}Coef${c}`] = splatShs [i];
2890
+ }
2849
2891
  }
2850
- }
2851
2892
 
2852
- parseMeta ()
2853
- {
2854
- return this .files .meta = JSON .parse (new TextDecoder () .decode (this .files ["meta.json"]));
2855
- }
2856
-
2857
- async unpackFiles ()
2858
- {
2859
- await this .unpackImages ();
2860
-
2861
- const
2862
- positions = this .unpackPositions (),
2863
- rotations = this .unpackRotations (),
2864
- scales = this .unpackScales (),
2865
- [alphas, colors] = this .unpackAlphasAndAColors (),
2866
- shs = this .unpackSphericalHarmonics ();
2867
-
2868
- return {
2869
- positions,
2870
- rotations,
2871
- scales,
2872
- alphas,
2873
- colors,
2874
- shs,
2893
+ parseMeta ()
2894
+ {
2895
+ return this .files .meta = JSON .parse (new TextDecoder () .decode (this .files ["meta.json"]));
2875
2896
  }
2876
- }
2877
-
2878
- async unpackImages ()
2879
- {
2880
- return Promise .all (Object .keys (this .files)
2881
- .filter (key => key .endsWith (".webp"))
2882
- .map (key => this .unpackImage (key)));
2883
- }
2884
2897
 
2885
- async unpackImage (key)
2886
- {
2887
- const
2888
- bytes = this .files [key],
2889
- blob = new Blob ([bytes], { type: "image/webp" }),
2890
- url = URL .createObjectURL (blob),
2891
- image = await this .loadImage (url),
2892
- data = this .readPixels (image);
2893
-
2894
- this .files [key] = image;
2895
- this .files [key .replace (".webp", "")] = data;
2898
+ async unpackFiles ()
2899
+ {
2900
+ await this .unpackImages ();
2896
2901
 
2897
- URL .revokeObjectURL (url);
2898
- }
2902
+ const
2903
+ positions = this .unpackPositions (),
2904
+ rotations = this .unpackRotations (),
2905
+ scales = this .unpackScales (),
2906
+ [alphas, colors] = this .unpackAlphasAndAColors (),
2907
+ shs = this .unpackSphericalHarmonics ();
2908
+
2909
+ return {
2910
+ positions,
2911
+ rotations,
2912
+ scales,
2913
+ alphas,
2914
+ colors,
2915
+ shs,
2916
+ }
2917
+ }
2899
2918
 
2900
- loadImage (url)
2901
- {
2902
- return new Promise ((resolve, reject) =>
2919
+ async unpackImages ()
2903
2920
  {
2904
- const image = new Image ();
2921
+ return Promise .all (Object .keys (this .files)
2922
+ .filter (key => key .endsWith (".webp"))
2923
+ .map (key => this .unpackImage (key)));
2924
+ }
2905
2925
 
2906
- image .onload = () => resolve (image);
2926
+ async unpackImage (key)
2927
+ {
2928
+ const
2929
+ bytes = this .files [key],
2930
+ blob = new Blob ([bytes], { type: "image/webp" }),
2931
+ url = URL .createObjectURL (blob),
2932
+ image = await this .loadImage (url),
2933
+ data = this .readPixels (image);
2907
2934
 
2908
- image .onerror =
2909
- image .onabort = event => reject (new Error (`Couldn't load WebP image: ${event .type}.`));
2935
+ this .files [key] = image;
2936
+ this .files [key .replace (".webp", "")] = data;
2910
2937
 
2911
- image .src = url;
2912
- });
2913
- }
2938
+ URL .revokeObjectURL (url);
2939
+ }
2914
2940
 
2915
- readPixels (image)
2916
- {
2917
- const
2918
- gl = this .getBrowser () .getContext (),
2919
- texture = gl .createTexture (),
2920
- framebuffer = gl .createFramebuffer (),
2921
- width = image .width,
2922
- height = image .height,
2923
- data = new Uint8Array (width * height * 4);
2941
+ loadImage (url)
2942
+ {
2943
+ return new Promise ((resolve, reject) =>
2944
+ {
2945
+ const image = new Image ();
2924
2946
 
2925
- // Create texture.
2947
+ image .onload = () => resolve (image);
2926
2948
 
2927
- gl .bindTexture (gl .TEXTURE_2D, texture);
2928
- gl .pixelStorei (gl .UNPACK_COLORSPACE_CONVERSION_WEBGL, gl .NONE);
2929
- gl .texImage2D (gl .TEXTURE_2D, 0, gl .RGBA, width, height, 0, gl .RGBA, gl .UNSIGNED_BYTE, image);
2930
- gl .pixelStorei (gl .UNPACK_COLORSPACE_CONVERSION_WEBGL, gl .BROWSER_DEFAULT_WEBGL);
2949
+ image .onerror =
2950
+ image .onabort = event => reject (new Error (`Couldn't load WebP image: ${event .type}.`));
2931
2951
 
2932
- // Read pixels from framebuffer.
2952
+ image .src = url;
2953
+ });
2954
+ }
2933
2955
 
2934
- gl .bindFramebuffer (gl .FRAMEBUFFER, framebuffer);
2935
- gl .framebufferTexture2D (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0, gl .TEXTURE_2D, texture, 0);
2936
- gl .readPixels (0, 0, width, height, gl .RGBA, gl .UNSIGNED_BYTE, data);
2956
+ readPixels (image)
2957
+ {
2958
+ const
2959
+ gl = this .getBrowser () .getContext (),
2960
+ texture = gl .createTexture (),
2961
+ framebuffer = gl .createFramebuffer (),
2962
+ width = image .width,
2963
+ height = image .height,
2964
+ data = new Uint8Array (width * height * 4);
2937
2965
 
2938
- // Clean up.
2966
+ // Create texture.
2939
2967
 
2940
- gl .deleteFramebuffer (framebuffer);
2941
- gl .deleteTexture (texture);
2968
+ gl .bindTexture (gl .TEXTURE_2D, texture);
2969
+ gl .pixelStorei (gl .UNPACK_COLORSPACE_CONVERSION_WEBGL, gl .NONE);
2970
+ gl .texImage2D (gl .TEXTURE_2D, 0, gl .RGBA, width, height, 0, gl .RGBA, gl .UNSIGNED_BYTE, image);
2971
+ gl .pixelStorei (gl .UNPACK_COLORSPACE_CONVERSION_WEBGL, gl .BROWSER_DEFAULT_WEBGL);
2942
2972
 
2943
- return data;
2944
- }
2973
+ // Read pixels from framebuffer.
2945
2974
 
2946
- unpackPositions ()
2947
- {
2948
- const lerp = (a, b, t) => a + t * (b - a);
2975
+ gl .bindFramebuffer (gl .FRAMEBUFFER, framebuffer);
2976
+ gl .framebufferTexture2D (gl .FRAMEBUFFER, gl .COLOR_ATTACHMENT0, gl .TEXTURE_2D, texture, 0);
2977
+ gl .readPixels (0, 0, width, height, gl .RGBA, gl .UNSIGNED_BYTE, data);
2949
2978
 
2950
- const unlog = n => Math .sign (n) * (Math .exp (Math .abs (n)) - 1);
2979
+ // Clean up.
2951
2980
 
2952
- const {
2953
- meta: { count, means: { mins, maxs }},
2954
- means_l,
2955
- means_u,
2956
- } = this .files;
2981
+ gl .deleteFramebuffer (framebuffer);
2982
+ gl .deleteTexture (texture);
2957
2983
 
2958
- const
2959
- N = count * 4,
2960
- array = [ ];
2984
+ return data;
2985
+ }
2961
2986
 
2962
- for (let i = 0; i < N; i += 4)
2987
+ unpackPositions ()
2963
2988
  {
2964
- // 16-bit normalized value per axis (0..65535)
2989
+ const lerp = (a, b, t) => a + t * (b - a);
2965
2990
 
2966
- const
2967
- qx = (means_u [i] << 8) | means_l [i],
2968
- qy = (means_u [i + 1] << 8) | means_l [i + 1],
2969
- qz = (means_u [i + 2] << 8) | means_l [i + 2];
2991
+ const unlog = n => Math .sign (n) * (Math .exp (Math .abs (n)) - 1);
2970
2992
 
2971
- // Dequantize into *log-domain* nx,ny,nz using per-axis ranges from meta:
2993
+ const {
2994
+ meta: { count, means: { mins, maxs }},
2995
+ means_l,
2996
+ means_u,
2997
+ } = this .files;
2972
2998
 
2973
2999
  const
2974
- nx = lerp (mins [0], maxs [0], qx / 65535),
2975
- ny = lerp (mins [1], maxs [1], qy / 65535),
2976
- nz = lerp (mins [2], maxs [2], qz / 65535);
3000
+ N = count * 4,
3001
+ array = [ ];
2977
3002
 
2978
- // Undo the symmetric log transform used at encode time:
3003
+ for (let i = 0; i < N; i += 4)
3004
+ {
3005
+ // 16-bit normalized value per axis (0..65535)
2979
3006
 
2980
- array .push (
2981
- unlog (nx),
2982
- unlog (ny),
2983
- unlog (nz),
2984
- );
2985
- }
3007
+ const
3008
+ qx = (means_u [i] << 8) | means_l [i],
3009
+ qy = (means_u [i + 1] << 8) | means_l [i + 1],
3010
+ qz = (means_u [i + 2] << 8) | means_l [i + 2];
2986
3011
 
2987
- return array;
2988
- }
3012
+ // Dequantize into *log-domain* nx,ny,nz using per-axis ranges from meta:
2989
3013
 
2990
- unpackRotations ()
2991
- {
2992
- const toComp = c => (c / 255 - 0.5) * 2 / Math .SQRT2;
3014
+ const
3015
+ nx = lerp (mins [0], maxs [0], qx / 65535),
3016
+ ny = lerp (mins [1], maxs [1], qy / 65535),
3017
+ nz = lerp (mins [2], maxs [2], qz / 65535);
2993
3018
 
2994
- const {
2995
- meta: { count },
2996
- quats,
2997
- } = this .files;
3019
+ // Undo the symmetric log transform used at encode time:
2998
3020
 
2999
- const
3000
- N = count * 4,
3001
- array = [ ];
3021
+ array .push (
3022
+ unlog (nx),
3023
+ unlog (ny),
3024
+ unlog (nz),
3025
+ );
3026
+ }
3002
3027
 
3003
- for (let i = 0; i < N; i += 4)
3004
- {
3005
- const
3006
- a = toComp (quats [i]),
3007
- b = toComp (quats [i + 1]),
3008
- c = toComp (quats [i + 2]);
3028
+ return array;
3029
+ }
3009
3030
 
3010
- const mode = quats [i + 3] - 252; // 0..3 → omitted component is w, x, y or z respectively
3031
+ unpackRotations ()
3032
+ {
3033
+ const toComp = c => (c / 255 - 0.5) * 2 / Math .SQRT2;
3011
3034
 
3012
- // Reconstruct the omitted component so that ||q|| = 1 and w.l.o.g. the omitted one is non-negative.
3035
+ const {
3036
+ meta: { count },
3037
+ quats,
3038
+ } = this .files;
3013
3039
 
3014
3040
  const
3015
- t = Math .hypot (a, b, c),
3016
- d = Math .sqrt (Math .max (0, 1 - t));
3017
-
3018
- // Place components according to mode; q is ordered [x, y, z, w].
3041
+ N = count * 4,
3042
+ array = [ ];
3019
3043
 
3020
- switch (mode)
3044
+ for (let i = 0; i < N; i += 4)
3021
3045
  {
3022
- case 0: array .push (a, b, c, d); break; // omitted = w
3023
- case 1: array .push (d, b, c, a); break; // omitted = x
3024
- case 2: array .push (b, d, c, a); break; // omitted = y
3025
- case 3: array .push (b, c, d, a); break; // omitted = z
3026
- default: throw new Error ("Invalid quaternion mode");
3027
- }
3028
- }
3046
+ const
3047
+ a = toComp (quats [i]),
3048
+ b = toComp (quats [i + 1]),
3049
+ c = toComp (quats [i + 2]);
3029
3050
 
3030
- return array;
3031
- }
3051
+ const mode = quats [i + 3] - 252; // 0..3 → omitted component is w, x, y or z respectively
3032
3052
 
3033
- unpackScales ()
3034
- {
3035
- const {
3036
- meta: { count, scales: { codebook } },
3037
- scales,
3038
- } = this .files;
3053
+ // Reconstruct the omitted component so that ||q|| = 1 and w.l.o.g. the omitted one is non-negative.
3039
3054
 
3040
- const
3041
- N = count * 4,
3042
- array = [ ];
3055
+ const
3056
+ t = Math .hypot (a, b, c),
3057
+ d = Math .sqrt (Math .max (0, 1 - t));
3058
+
3059
+ // Place components according to mode; q is ordered [x, y, z, w].
3060
+
3061
+ switch (mode)
3062
+ {
3063
+ case 0: array .push (a, b, c, d); break; // omitted = w
3064
+ case 1: array .push (d, b, c, a); break; // omitted = x
3065
+ case 2: array .push (b, d, c, a); break; // omitted = y
3066
+ case 3: array .push (b, c, d, a); break; // omitted = z
3067
+ default: throw new Error ("Invalid quaternion mode");
3068
+ }
3069
+ }
3043
3070
 
3044
- for (let i = 0; i < N; i += 4)
3045
- {
3046
- array .push (
3047
- Math .exp (codebook [scales [i]]), // r,g,b are 0..255
3048
- Math .exp (codebook [scales [i + 1]]),
3049
- Math .exp (codebook [scales [i + 2]]),
3050
- );
3071
+ return array;
3051
3072
  }
3052
3073
 
3053
- return array;
3054
- }
3055
-
3056
- unpackAlphasAndAColors ()
3057
- {
3058
- const {
3059
- meta: { count, sh0: { codebook } },
3060
- sh0,
3061
- } = this .files;
3074
+ unpackScales ()
3075
+ {
3076
+ const {
3077
+ meta: { count, scales: { codebook } },
3078
+ scales,
3079
+ } = this .files;
3062
3080
 
3063
- const
3064
- N = count * 4,
3065
- array = [ ],
3066
- alphas = [ ];
3081
+ const
3082
+ N = count * 4,
3083
+ array = [ ];
3067
3084
 
3068
- for (let i = 0; i < N; i += 4)
3069
- {
3070
- array .push (
3071
- codebook [sh0 [i]],
3072
- codebook [sh0 [i + 1]],
3073
- codebook [sh0 [i + 2]],
3074
- );
3085
+ for (let i = 0; i < N; i += 4)
3086
+ {
3087
+ array .push (
3088
+ Math .exp (codebook [scales [i]]), // r,g,b are 0..255
3089
+ Math .exp (codebook [scales [i + 1]]),
3090
+ Math .exp (codebook [scales [i + 2]]),
3091
+ );
3092
+ }
3075
3093
 
3076
- alphas .push (sh0 [i + 3] / 255);
3094
+ return array;
3077
3095
  }
3078
3096
 
3079
- return [alphas, array];
3080
- }
3097
+ unpackAlphasAndAColors ()
3098
+ {
3099
+ const {
3100
+ meta: { count, sh0: { codebook } },
3101
+ sh0,
3102
+ } = this .files;
3081
3103
 
3082
- unpackSphericalHarmonics ()
3083
- {
3084
- if (!this .files .meta .shN)
3085
- return [ ];
3104
+ const
3105
+ N = count * 4,
3106
+ array = [ ],
3107
+ alphas = [ ];
3086
3108
 
3087
- const {
3088
- meta: { count, shN: { bands, codebook } },
3089
- shN_labels,
3090
- shN_centroids,
3091
- "shN_centroids.webp": { width },
3092
- } = this .files;
3109
+ for (let i = 0; i < N; i += 4)
3110
+ {
3111
+ array .push (
3112
+ codebook [sh0 [i]],
3113
+ codebook [sh0 [i + 1]],
3114
+ codebook [sh0 [i + 2]],
3115
+ );
3093
3116
 
3094
- const getIndex = (u, v) => u + v * width;
3117
+ alphas .push (sh0 [i + 3] / 255);
3118
+ }
3095
3119
 
3096
- const
3097
- coeffs = [0, 3, 8, 15],
3098
- shCoeffs = coeffs [bands]; // coefficients per color channel
3120
+ return [alphas, array];
3121
+ }
3099
3122
 
3100
- if (!shCoeffs)
3101
- return [ ];
3123
+ unpackSphericalHarmonics ()
3124
+ {
3125
+ if (!this .files .meta .shN)
3126
+ return [ ];
3102
3127
 
3103
- const
3104
- N = count * 4,
3105
- array = [ ];
3128
+ const {
3129
+ meta: { count, shN: { bands, codebook } },
3130
+ shN_labels,
3131
+ shN_centroids,
3132
+ "shN_centroids.webp": { width },
3133
+ } = this .files;
3106
3134
 
3107
- for (let i = 0; i < N; i += 4)
3108
- {
3109
- // 1. Look up this gaussian's palette entry.
3135
+ const getIndex = (u, v) => u + v * width;
3110
3136
 
3111
- const label = shN_labels [i] + (shN_labels [i + 1] << 8);
3137
+ const
3138
+ coeffs = [0, 3, 8, 15],
3139
+ shCoeffs = coeffs [bands]; // coefficients per color channel
3112
3140
 
3113
- // 2. For each coefficient, read RGB from the centroids pixel and map through the codebook.
3141
+ if (!shCoeffs)
3142
+ return [ ];
3114
3143
 
3115
- for (let c = 0; c < shCoeffs; ++ c)
3144
+ const
3145
+ N = count * 4,
3146
+ array = [ ];
3147
+
3148
+ for (let i = 0; i < N; i += 4)
3116
3149
  {
3117
- const
3118
- u = (label % 64) * shCoeffs + c,
3119
- v = Math .floor (label / 64);
3150
+ // 1. Look up this gaussian's palette entry.
3120
3151
 
3121
- // pixel (u, v) in shN_centroids.webp
3122
- const index = getIndex (u, v) * 4;
3152
+ const label = shN_labels [i] + (shN_labels [i + 1] << 8);
3123
3153
 
3124
- const
3125
- r = shN_centroids [index],
3126
- g = shN_centroids [index + 1],
3127
- b = shN_centroids [index + 2];
3154
+ // 2. For each coefficient, read RGB from the centroids pixel and map through the codebook.
3128
3155
 
3129
- array .push (
3130
- codebook [r], // SH AC coefficient for color channel 0
3131
- codebook [g], // SH AC coefficient for color channel 1
3132
- codebook [b], // SH AC coefficient for color channel 2
3133
- );
3134
- }
3135
- }
3156
+ for (let c = 0; c < shCoeffs; ++ c)
3157
+ {
3158
+ const
3159
+ u = (label % 64) * shCoeffs + c,
3160
+ v = Math .floor (label / 64);
3136
3161
 
3137
- return array;
3138
- }
3139
-
3140
- dimForDegree (degree)
3141
- {
3142
- return (degree + 1) ** 2 - 1;
3143
- }
3162
+ // pixel (u, v) in shN_centroids.webp
3163
+ const index = getIndex (u, v) * 4;
3144
3164
 
3145
- coefsForDegree (degree)
3146
- {
3147
- return degree * 2 + 3;
3148
- }
3149
- }
3165
+ const
3166
+ r = shN_centroids [index],
3167
+ g = shN_centroids [index + 1],
3168
+ b = shN_centroids [index + 2];
3150
3169
 
3151
- X3D .GoldenGate .addParsers (SOGParser);
3170
+ array .push (
3171
+ codebook [r], // SH AC coefficient for color channel 0
3172
+ codebook [g], // SH AC coefficient for color channel 1
3173
+ codebook [b], // SH AC coefficient for color channel 2
3174
+ );
3175
+ }
3176
+ }
3152
3177
 
3153
- // Decrement extensions attribute to show that the parser is loaded.
3178
+ return array;
3179
+ }
3154
3180
 
3155
- const canvases = document .querySelectorAll ("x3d-canvas");
3181
+ dimForDegree (degree)
3182
+ {
3183
+ return (degree + 1) ** 2 - 1;
3184
+ }
3156
3185
 
3157
- for (const canvas of canvases)
3158
- {
3159
- const { element } = X3D .getBrowser (canvas);
3186
+ coefsForDegree (degree)
3187
+ {
3188
+ return degree * 2 + 3;
3189
+ }
3190
+ }
3160
3191
 
3161
- element .setAttribute ("extensions", Math .max ((element .getAttribute ("extensions")|0) - 1, 0));
3162
- }
3192
+ X3D .GoldenGate .addParsers (SOGParser);
3193
+ });
3163
3194
 
3164
3195
  /******/ })()
3165
3196
  ;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x_ite-sog-parser",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "3DGS SOG File Format Parser for X_ITE",
5
5
  "main": "dist/x_ite-sog-parser-2.js",
6
6
  "module": "dist/x_ite-sog-parser-2.js",
@@ -44,6 +44,7 @@
44
44
  "globals": "^17.6.0",
45
45
  "shell-tools": "^1.1.9",
46
46
  "webpack": "^5.107.2",
47
- "webpack-cli": "^7.0.3"
47
+ "webpack-cli": "^7.0.3",
48
+ "x_ite-extension": "^1.0.0"
48
49
  }
49
50
  }