@threepipe/plugin-gaussian-splatting 0.2.1 → 0.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.
Files changed (31) hide show
  1. package/dist/assets/{worker-BYCkgQO3.js.map → worker-CZa3bSRr.js.map} +1 -1
  2. package/dist/gaussian-splats-3d/GaussianSplatsPlugin.d.ts +1 -0
  3. package/dist/gaussian-splats-3d/GaussianSplatsPlugin.d.ts.map +1 -0
  4. package/dist/index.js +6 -6
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +6 -6
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/three-gaussian-splat/ThreeGaussianSplatPlugin.d.ts +9 -9
  9. package/dist/three-gaussian-splat/ThreeGaussianSplatPlugin.d.ts.map +1 -1
  10. package/dist/three-gaussian-splat/cpp-sorter/SortWorkerManager.d.ts +1 -1
  11. package/dist/three-gaussian-splat/cpp-sorter/worker.d.ts +1 -2
  12. package/dist/three-gaussian-splat/cpp-sorter/worker.d.ts.map +1 -1
  13. package/dist/three-gaussian-splat/geometry/GaussianSplatGeometry.d.ts +6 -5
  14. package/dist/three-gaussian-splat/geometry/GaussianSplatGeometry.d.ts.map +1 -1
  15. package/package.json +13 -2
  16. package/src/three-gaussian-splat/geometry/GaussianSplatGeometry.ts +1 -0
  17. package/src/gaussian-splats-3d/Constants.js +0 -10
  18. package/src/gaussian-splats-3d/Util.js +0 -147
  19. package/src/gaussian-splats-3d/loaders/KSplatLoader.js +0 -238
  20. package/src/gaussian-splats-3d/loaders/LoaderStatus.js +0 -6
  21. package/src/gaussian-splats-3d/loaders/PlyLoader.js +0 -32
  22. package/src/gaussian-splats-3d/loaders/PlyParser.js +0 -188
  23. package/src/gaussian-splats-3d/loaders/SceneFormat.js +0 -5
  24. package/src/gaussian-splats-3d/loaders/SplatBuffer.js +0 -817
  25. package/src/gaussian-splats-3d/loaders/SplatBufferGenerator.js +0 -31
  26. package/src/gaussian-splats-3d/loaders/SplatLoader.js +0 -129
  27. package/src/gaussian-splats-3d/loaders/SplatParser.js +0 -88
  28. package/src/gaussian-splats-3d/loaders/SplatPartitioner.js +0 -99
  29. package/src/gaussian-splats-3d/loaders/UncompressedSplatArray.js +0 -49
  30. package/src/gaussian-splats-3d/loaders/Utils.js +0 -8
  31. package/src/gaussian-splats-3d/loaders-ts/SplatLoader.ts +0 -33
@@ -1,238 +0,0 @@
1
- import { SplatBuffer } from './SplatBuffer.js';
2
- import { fetchWithProgress, delayedExecute } from '../Util.js';
3
- import { LoaderStatus } from './LoaderStatus.js';
4
- import { Constants } from '../Constants.js';
5
-
6
- const MINIMUM_REQUIRED_MAJOR_VERSION = 0;
7
- const MINIMUM_REQUIRED_MINOR_VERSION = 1;
8
-
9
- export class KSplatLoader {
10
-
11
- constructor(splatBuffer = null) {
12
- this.splatBuffer = splatBuffer;
13
- this.downLoadLink = null;
14
- }
15
-
16
- static checkVersion(buffer) {
17
- const header = SplatBuffer.parseHeader(buffer);
18
- if (header.versionMajor === MINIMUM_REQUIRED_MAJOR_VERSION && header.versionMinor >= MINIMUM_REQUIRED_MINOR_VERSION ||
19
- header.versionMajor > MINIMUM_REQUIRED_MAJOR_VERSION) {
20
- return true;
21
- } else {
22
- throw new Error(`KSplat version not supported: v${header.versionMajor}.${header.versionMinor}. ` +
23
- `Minimum required: v${MINIMUM_REQUIRED_MAJOR_VERSION}.${MINIMUM_REQUIRED_MINOR_VERSION}`);
24
- }
25
- };
26
-
27
- loadFromURL(fileName, onProgress, streamBuiltSections, onSectionBuilt) {
28
- let bytesLoaded = 0;
29
- let totalStorageSizeBytes = 0;
30
-
31
- let streamBuffer;
32
- let streamSplatBuffer;
33
-
34
- let headerBuffer;
35
- let header;
36
- let headerLoaded = false;
37
- let headerLoading = false;
38
-
39
- let sectionHeadersBuffer;
40
- let sectionHeaders = [];
41
- let sectionHeadersLoaded = false;
42
- let sectionHeadersLoading = false;
43
-
44
- let lastStreamUpdateBytes = 0;
45
- let streamSectionSizeBytes = Constants.StreamingSectionSize;
46
- let totalBytesToDownload = 0;
47
-
48
- let loadComplete = false;
49
-
50
- let chunks = [];
51
-
52
- let streamLoadCompleteResolver;
53
- let streamLoadPromise = new Promise((resolve) => {
54
- streamLoadCompleteResolver = resolve;
55
- });
56
-
57
- const checkAndLoadHeader = () => {
58
- if (!headerLoaded && !headerLoading && bytesLoaded >= SplatBuffer.HeaderSizeBytes) {
59
- headerLoading = true;
60
- const headerAssemblyPromise = new Blob(chunks).arrayBuffer();
61
- headerAssemblyPromise.then((bufferData) => {
62
- headerBuffer = new ArrayBuffer(SplatBuffer.HeaderSizeBytes);
63
- new Uint8Array(headerBuffer).set(new Uint8Array(bufferData, 0, SplatBuffer.HeaderSizeBytes));
64
- KSplatLoader.checkVersion(headerBuffer);
65
- headerLoading = false;
66
- headerLoaded = true;
67
- header = SplatBuffer.parseHeader(headerBuffer);
68
- window.setTimeout(() => {
69
- checkAndLoadSectionHeaders();
70
- }, 1);
71
- });
72
- }
73
- };
74
-
75
- let queuedCheckAndLoadSectionsCount = 0;
76
- const queueCheckAndLoadSections = () => {
77
- if (queuedCheckAndLoadSectionsCount === 0) {
78
- queuedCheckAndLoadSectionsCount++;
79
- window.setTimeout(() => {
80
- queuedCheckAndLoadSectionsCount--;
81
- checkAndLoadSections(true);
82
- }, 1);
83
- }
84
- };
85
-
86
- const checkAndLoadSectionHeaders = () => {
87
- const performLoad = () => {
88
- sectionHeadersLoading = true;
89
- const sectionHeadersAssemblyPromise = new Blob(chunks).arrayBuffer();
90
- sectionHeadersAssemblyPromise.then((bufferData) => {
91
- sectionHeadersLoading = false;
92
- sectionHeadersLoaded = true;
93
- sectionHeadersBuffer = new ArrayBuffer(header.maxSectionCount * SplatBuffer.SectionHeaderSizeBytes);
94
- new Uint8Array(sectionHeadersBuffer).set(new Uint8Array(bufferData, SplatBuffer.HeaderSizeBytes,
95
- header.maxSectionCount * SplatBuffer.SectionHeaderSizeBytes));
96
- sectionHeaders = SplatBuffer.parseSectionHeaders(header, sectionHeadersBuffer, 0, false);
97
- let totalSectionStorageStorageByes = 0;
98
- for (let i = 0; i < header.maxSectionCount; i++) {
99
- totalSectionStorageStorageByes += sectionHeaders[i].storageSizeBytes;
100
- }
101
- totalStorageSizeBytes = SplatBuffer.HeaderSizeBytes + header.maxSectionCount *
102
- SplatBuffer.SectionHeaderSizeBytes + totalSectionStorageStorageByes;
103
- if (!streamBuffer) {
104
- streamBuffer = new ArrayBuffer(totalStorageSizeBytes);
105
- let offset = 0;
106
- for (let i = 0; i < chunks.length; i++) {
107
- const chunk = chunks[i];
108
- new Uint8Array(streamBuffer, offset, chunk.byteLength).set(new Uint8Array(chunk));
109
- offset += chunk.byteLength;
110
- }
111
- }
112
-
113
- totalBytesToDownload = SplatBuffer.HeaderSizeBytes + SplatBuffer.SectionHeaderSizeBytes * header.maxSectionCount;
114
- for (let i = 0; i <= sectionHeaders.length && i < header.maxSectionCount; i++) {
115
- totalBytesToDownload += sectionHeaders[i].storageSizeBytes;
116
- }
117
-
118
- queueCheckAndLoadSections();
119
- });
120
- };
121
-
122
- if (!sectionHeadersLoading && !sectionHeadersLoaded && headerLoaded &&
123
- bytesLoaded >= SplatBuffer.HeaderSizeBytes + SplatBuffer.SectionHeaderSizeBytes * header.maxSectionCount) {
124
- performLoad();
125
- }
126
- };
127
-
128
- const checkAndLoadSections = () => {
129
- if (sectionHeadersLoaded) {
130
-
131
- if (loadComplete) return;
132
-
133
- loadComplete = bytesLoaded >= totalBytesToDownload;
134
-
135
- const bytesLoadedSinceLastSection = bytesLoaded - lastStreamUpdateBytes;
136
- if (bytesLoadedSinceLastSection > streamSectionSizeBytes || loadComplete) {
137
-
138
- lastStreamUpdateBytes = bytesLoaded;
139
-
140
- if (!streamSplatBuffer) streamSplatBuffer = new SplatBuffer(streamBuffer, false);
141
-
142
- const baseDataOffset = SplatBuffer.HeaderSizeBytes + SplatBuffer.SectionHeaderSizeBytes * header.maxSectionCount;
143
- let sectionBase = 0;
144
- let reachedSections = 0;
145
- let loadedSplatCount = 0;
146
- for (let i = 0; i < header.maxSectionCount; i++) {
147
- const sectionHeader = sectionHeaders[i];
148
- const bucketsDataOffset = sectionBase + sectionHeader.partiallyFilledBucketCount * 4 +
149
- sectionHeader.bucketStorageSizeBytes * sectionHeader.bucketCount;
150
- const bytesRequiredToReachSectionSplatData = baseDataOffset + bucketsDataOffset;
151
- if (bytesLoaded >= bytesRequiredToReachSectionSplatData) {
152
- reachedSections++;
153
- const bytesPastSSectionSplatDataStart = bytesLoaded - bytesRequiredToReachSectionSplatData;
154
- const bytesPerSplat = SplatBuffer.CompressionLevels[header.compressionLevel].BytesPerSplat;
155
- let loadedSplatsForSection = Math.floor(bytesPastSSectionSplatDataStart / bytesPerSplat);
156
- loadedSplatsForSection = Math.min(loadedSplatsForSection, sectionHeader.maxSplatCount);
157
- loadedSplatCount += loadedSplatsForSection;
158
- streamSplatBuffer.updateLoadedCounts(reachedSections, loadedSplatCount);
159
- streamSplatBuffer.updateSectionLoadedCounts(i, loadedSplatsForSection);
160
- } else {
161
- break;
162
- }
163
- sectionBase += sectionHeader.storageSizeBytes;
164
- }
165
-
166
- onSectionBuilt(streamSplatBuffer, loadComplete);
167
-
168
- if (loadComplete) {
169
- streamLoadCompleteResolver();
170
- }
171
- }
172
- }
173
- };
174
-
175
- const localOnProgress = (percent, percentStr, chunk) => {
176
-
177
- if (chunk) {
178
- chunks.push(chunk);
179
- if (streamBuffer) {
180
- new Uint8Array(streamBuffer, bytesLoaded, chunk.byteLength).set(new Uint8Array(chunk));
181
- }
182
- bytesLoaded += chunk.byteLength;
183
- }
184
- if (streamBuiltSections) {
185
- checkAndLoadHeader();
186
- checkAndLoadSectionHeaders();
187
- checkAndLoadSections();
188
- }
189
- if (onProgress) onProgress(percent, percentStr, LoaderStatus.Downloading);
190
- };
191
-
192
- return fetchWithProgress(fileName, localOnProgress, !streamBuiltSections).then((fullBuffer) => {
193
- if (onProgress) onProgress(0, '0%', LoaderStatus.Processing);
194
- return delayedExecute(() => {
195
- function finish(buffer) {
196
- if (onProgress) onProgress(100, '100%', LoaderStatus.Done);
197
- if (buffer instanceof SplatBuffer) return buffer;
198
- else {
199
- KSplatLoader.checkVersion(buffer);
200
- return new SplatBuffer(buffer);
201
- }
202
- }
203
- if (streamBuiltSections) {
204
- return streamLoadPromise.then(() => {
205
- return finish(streamSplatBuffer);
206
- });
207
- } else {
208
- return finish(fullBuffer);
209
- }
210
- });
211
- });
212
- }
213
-
214
- setFromBuffer(splatBuffer) {
215
- this.splatBuffer = splatBuffer;
216
- }
217
-
218
- static downloadFile = function() {
219
-
220
- let downLoadLink;
221
-
222
- return function(splatBuffer, fileName) {
223
- const blob = new Blob([splatBuffer.bufferData], {
224
- type: 'application/octet-stream',
225
- });
226
-
227
- if (!downLoadLink) {
228
- downLoadLink = document.createElement('a');
229
- document.body.appendChild(downLoadLink);
230
- }
231
- downLoadLink.download = fileName;
232
- downLoadLink.href = URL.createObjectURL(blob);
233
- downLoadLink.click();
234
- };
235
-
236
- }();
237
-
238
- }
@@ -1,6 +0,0 @@
1
- export const LoaderStatus = {
2
- 'Downloading': 0,
3
- 'Processing': 1,
4
- 'Done': 2,
5
- };
6
-
@@ -1,32 +0,0 @@
1
- import {PlyParser} from './PlyParser.js';
2
- import {delayedExecute, fetchWithProgress} from '../Util.js';
3
- import {LoaderStatus} from './LoaderStatus.js';
4
- import {SplatBufferGenerator} from './SplatBufferGenerator.js';
5
-
6
- export class PlyLoader {
7
-
8
- constructor () {
9
- this.splatBuffer = null;
10
- }
11
-
12
- loadFromURL (fileName, onProgress, compressionLevel, minimumAlpha, sectionSize, sceneCenter, blockSize, bucketSize) {
13
- const downloadProgress = (percent, percentLabel) => {
14
- if (onProgress) onProgress(percent, percentLabel, LoaderStatus.Downloading);
15
- };
16
- return fetchWithProgress(fileName, downloadProgress).then((plyFileData) => {
17
- if (onProgress) onProgress(0, '0%', LoaderStatus.Processing);
18
- return delayedExecute(() => {
19
- return new PlyParser(plyFileData).parseToUncompressedSplatArray();
20
- });
21
- })
22
- .then((splatArray) => {
23
- const splatBufferGenerator = SplatBufferGenerator.getStandardGenerator(minimumAlpha,
24
- compressionLevel, sectionSize,
25
- sceneCenter, blockSize, bucketSize);
26
- const splatBuffer = splatBufferGenerator.generateFromUncompressedSplatArray(splatArray);
27
- if (onProgress) onProgress(100, '100%', LoaderStatus.Done);
28
- return splatBuffer;
29
- });
30
- }
31
-
32
- }
@@ -1,188 +0,0 @@
1
- import {UncompressedSplatArray} from './UncompressedSplatArray.js';
2
-
3
- export class PlyParser {
4
-
5
- static HeaderEndToken = 'end_header';
6
-
7
- constructor (plyBuffer) {
8
- this.plyBuffer = plyBuffer;
9
- }
10
-
11
- static decodeHeader (plyBuffer) {
12
- const decoder = new TextDecoder();
13
- let headerOffset = 0;
14
- let headerText = '';
15
-
16
- // console.log('.PLY size: ' + plyBuffer.byteLength + ' bytes');
17
-
18
- const readChunkSize = 100;
19
-
20
- while (true) {
21
- if (headerOffset + readChunkSize >= plyBuffer.byteLength) {
22
- throw new Error('End of file reached while searching for end of header');
23
- }
24
- const headerChunk = new Uint8Array(plyBuffer, headerOffset, readChunkSize);
25
- headerText += decoder.decode(headerChunk);
26
- headerOffset += readChunkSize;
27
-
28
- const endHeaderTestChunk = new Uint8Array(plyBuffer, Math.max(0, headerOffset - readChunkSize * 2), readChunkSize * 2);
29
- const endHeaderTestText = decoder.decode(endHeaderTestChunk);
30
- if (endHeaderTestText.includes('end_header')) {
31
- break;
32
- }
33
- }
34
-
35
- const headerLines = headerText.split('\n');
36
-
37
- let splatCount = 0;
38
- let propertyTypes = {};
39
-
40
- for (let i = 0; i < headerLines.length; i++) {
41
- const line = headerLines[i].trim();
42
- if (line.startsWith('element vertex')) {
43
- const splatCountMatch = line.match(/\d+/);
44
- if (splatCountMatch) {
45
- splatCount = parseInt(splatCountMatch[0]);
46
- }
47
- } else if (line.startsWith('property')) {
48
- const propertyMatch = line.match(/(\w+)\s+(\w+)\s+(\w+)/);
49
- if (propertyMatch) {
50
- const propertyType = propertyMatch[2];
51
- const propertyName = propertyMatch[3];
52
- propertyTypes[propertyName] = propertyType;
53
- }
54
- } else if (line === 'end_header') {
55
- break;
56
- }
57
- }
58
-
59
- const vertexByteOffset = headerText.indexOf('end_header') + PlyParser.HeaderEndToken.length + 1;
60
- const vertexData = new DataView(plyBuffer, vertexByteOffset);
61
-
62
- return {
63
- 'splatCount': splatCount,
64
- 'propertyTypes': propertyTypes,
65
- 'vertexData': vertexData,
66
- 'headerOffset': headerOffset,
67
- };
68
- }
69
-
70
- static readRawVertexFast (vertexData, offset, fieldOffsets, propertiesToRead, propertyTypes, outVertex) {
71
- let rawVertex = outVertex || {};
72
- for (let property of propertiesToRead) {
73
- const propertyType = propertyTypes[property];
74
- if (propertyType === 'float') {
75
- rawVertex[property] = vertexData.getFloat32(offset + fieldOffsets[property], true);
76
- } else if (propertyType === 'uchar') {
77
- rawVertex[property] = vertexData.getUint8(offset + fieldOffsets[property]) / 255.0;
78
- }
79
- }
80
- }
81
-
82
- parseToUncompressedSplatArray () {
83
-
84
- // const startTime = performance.now();
85
-
86
- // console.log('Parsing PLY to SPLAT...');
87
-
88
- const {splatCount, propertyTypes, vertexData} = PlyParser.decodeHeader(this.plyBuffer);
89
-
90
- // figure out the SH degree from the number of coefficients
91
- let nRestCoeffs = 0;
92
- for (const propertyName in propertyTypes) {
93
- if (propertyName.startsWith('f_rest_')) {
94
- nRestCoeffs += 1;
95
- }
96
- }
97
- const nCoeffsPerColor = nRestCoeffs / 3;
98
-
99
- // TODO: Eventually properly support multiple degree spherical harmonics
100
- // const sphericalHarmonicsDegree = Math.sqrt(nCoeffsPerColor + 1) - 1;
101
- // const sphericalHarmonicsDegree = 0;
102
- // console.log('Detected degree', sphericalHarmonicsDegree, 'with ', nCoeffsPerColor, 'coefficients per color');
103
-
104
- // figure out the order in which spherical harmonics should be read
105
- const shFeatureOrder = [];
106
- for (let rgb = 0; rgb < 3; ++rgb) {
107
- shFeatureOrder.push(`f_dc_${rgb}`);
108
- }
109
- for (let i = 0; i < nCoeffsPerColor; ++i) {
110
- for (let rgb = 0; rgb < 3; ++rgb) {
111
- shFeatureOrder.push(`f_rest_${rgb * nCoeffsPerColor + i}`);
112
- }
113
- }
114
-
115
- let plyRowSize = 0;
116
- let fieldOffsets = {};
117
- const fieldSize = {
118
- 'double': 8,
119
- 'int': 4,
120
- 'uint': 4,
121
- 'float': 4,
122
- 'short': 2,
123
- 'ushort': 2,
124
- 'uchar': 1,
125
- };
126
- for (let fieldName in propertyTypes) {
127
- if (propertyTypes.hasOwnProperty(fieldName)) {
128
- const type = propertyTypes[fieldName];
129
- fieldOffsets[fieldName] = plyRowSize;
130
- plyRowSize += fieldSize[type];
131
- }
132
- }
133
-
134
- let rawVertex = {};
135
-
136
- const propertiesToRead = ['scale_0', 'scale_1', 'scale_2', 'rot_0', 'rot_1', 'rot_2', 'rot_3',
137
- 'x', 'y', 'z', 'f_dc_0', 'f_dc_1', 'f_dc_2', 'opacity'];
138
-
139
- const splatArray = new UncompressedSplatArray();
140
-
141
- for (let row = 0; row < splatCount; row++) {
142
- PlyParser.readRawVertexFast(vertexData, row * plyRowSize, fieldOffsets, propertiesToRead, propertyTypes, rawVertex);
143
- const newSplat = splatArray.addDefaultSplat();
144
- if (rawVertex['scale_0'] !== undefined) {
145
- newSplat[UncompressedSplatArray.OFFSET.SCALE0] = Math.exp(rawVertex['scale_0']);
146
- newSplat[UncompressedSplatArray.OFFSET.SCALE1] = Math.exp(rawVertex['scale_1']);
147
- newSplat[UncompressedSplatArray.OFFSET.SCALE2] = Math.exp(rawVertex['scale_2']);
148
- } else {
149
- newSplat[UncompressedSplatArray.OFFSET.SCALE0] = 0.01;
150
- newSplat[UncompressedSplatArray.OFFSET.SCALE1] = 0.01;
151
- newSplat[UncompressedSplatArray.OFFSET.SCALE2] = 0.01;
152
- }
153
-
154
- if (rawVertex['f_dc_0'] !== undefined) {
155
- const SH_C0 = 0.28209479177387814;
156
- newSplat[UncompressedSplatArray.OFFSET.FDC0] = (0.5 + SH_C0 * rawVertex['f_dc_0']) * 255;
157
- newSplat[UncompressedSplatArray.OFFSET.FDC1] = (0.5 + SH_C0 * rawVertex['f_dc_1']) * 255;
158
- newSplat[UncompressedSplatArray.OFFSET.FDC2] = (0.5 + SH_C0 * rawVertex['f_dc_2']) * 255;
159
- } else {
160
- newSplat[UncompressedSplatArray.OFFSET.FDC0] = 0;
161
- newSplat[UncompressedSplatArray.OFFSET.FDC1] = 0;
162
- newSplat[UncompressedSplatArray.OFFSET.FDC2] = 0;
163
- }
164
- if (rawVertex['opacity'] !== undefined) {
165
- newSplat[UncompressedSplatArray.OFFSET.OPACITY] = (1 / (1 + Math.exp(-rawVertex['opacity']))) * 255;
166
- }
167
-
168
- newSplat[UncompressedSplatArray.OFFSET.ROTATION0] = rawVertex['rot_0'];
169
- newSplat[UncompressedSplatArray.OFFSET.ROTATION1] = rawVertex['rot_1'];
170
- newSplat[UncompressedSplatArray.OFFSET.ROTATION2] = rawVertex['rot_2'];
171
- newSplat[UncompressedSplatArray.OFFSET.ROTATION3] = rawVertex['rot_3'];
172
-
173
- newSplat[UncompressedSplatArray.OFFSET.X] = rawVertex['x'];
174
- newSplat[UncompressedSplatArray.OFFSET.Y] = rawVertex['y'];
175
- newSplat[UncompressedSplatArray.OFFSET.Z] = rawVertex['z'];
176
- }
177
-
178
- return splatArray;
179
-
180
- // console.log('Total valid splats: ', splatBuffer.getSplatCount(), 'out of', splatCount);
181
-
182
- // const endTime = performance.now();
183
-
184
- // console.log('Parsing PLY to SPLAT complete!');
185
- // console.log('Total time: ', (endTime - startTime).toFixed(2) + ' ms');
186
- }
187
-
188
- }
@@ -1,5 +0,0 @@
1
- export const SceneFormat = {
2
- 'Splat': 0,
3
- 'KSplat': 1,
4
- 'Ply': 2
5
- };