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