Skip to content

Commit c1034c3

Browse files
authored
Store PLY header comments (#7246)
1 parent 456f872 commit c1034c3

File tree

2 files changed

+52
-33
lines changed

2 files changed

+52
-33
lines changed

src/framework/parsers/gsplat-resource.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,22 @@ class GSplatResource {
3333
*/
3434
splat = null;
3535

36+
/**
37+
* @type {string[] | null}
38+
* @ignore
39+
*/
40+
comments = null;
41+
3642
/**
3743
* @param {GraphicsDevice} device - The graphics device.
3844
* @param {GSplatData} splatData - The splat data.
45+
* @param {string[]} comments - The PLY file header comments
3946
* @ignore
4047
*/
41-
constructor(device, splatData) {
48+
constructor(device, splatData, comments) {
4249
this.device = device;
4350
this.splatData = splatData;
51+
this.comments = comments;
4452
}
4553

4654
destroy() {

src/framework/parsers/ply.js

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,16 @@ class StreamBuf {
162162
// string containing the ply format
163163
const parseHeader = (lines) => {
164164
const elements = [];
165+
const comments = [];
165166
let format;
166167

167168
for (let i = 1; i < lines.length; ++i) {
168169
const words = lines[i].split(' ');
169170

170171
switch (words[0]) {
172+
case 'comment':
173+
comments.push(words.slice(1).join(' '));
174+
break;
171175
case 'format':
172176
format = words[1];
173177
break;
@@ -196,7 +200,7 @@ const parseHeader = (lines) => {
196200
}
197201
}
198202

199-
return { elements, format };
203+
return { elements, format, comments };
200204
};
201205

202206
// return true if the array of elements references a compressed ply file
@@ -239,7 +243,7 @@ const isFloatPly = (elements) => {
239243
};
240244

241245
// read the data of a compressed ply file
242-
const readCompressedPly = async (streamBuf, elements, littleEndian) => {
246+
const readCompressedPly = async (streamBuf, elements) => {
243247
const result = new GSplatCompressedData();
244248

245249
const numChunks = elements[0].count;
@@ -294,7 +298,7 @@ const readCompressedPly = async (streamBuf, elements, littleEndian) => {
294298
};
295299

296300
// read the data of a floating point ply file
297-
const readFloatPly = async (streamBuf, elements, littleEndian) => {
301+
const readFloatPly = async (streamBuf, elements) => {
298302
// calculate the size of an input element record
299303
const element = elements[0];
300304
const properties = element.properties;
@@ -336,7 +340,7 @@ const readFloatPly = async (streamBuf, elements, littleEndian) => {
336340
return new GSplatData(elements);
337341
};
338342

339-
const readGeneralPly = async (streamBuf, elements, littleEndian) => {
343+
const readGeneralPly = async (streamBuf, elements) => {
340344
// read and deinterleave the data
341345
for (let i = 0; i < elements.length; ++i) {
342346
const element = elements[i];
@@ -391,7 +395,7 @@ const readGeneralPly = async (streamBuf, elements, littleEndian) => {
391395
*
392396
* @param {ReadableStreamDefaultReader<Uint8Array>} reader - The reader.
393397
* @param {Function|null} propertyFilter - Function to filter properties with.
394-
* @returns {Promise<GSplatData | GSplatCompressedData>} The ply file data.
398+
* @returns {Promise<{ data: GSplatData | GSplatCompressedData, comments: string[] }>} The ply file data.
395399
*/
396400
const readPly = async (reader, propertyFilter = null) => {
397401
/**
@@ -464,14 +468,13 @@ const readPly = async (reader, propertyFilter = null) => {
464468
// decode buffer header text and split into lines and remove comments
465469
const lines = new TextDecoder('ascii')
466470
.decode(streamBuf.data.subarray(0, headerLength))
467-
.split('\n')
468-
.filter(line => !line.startsWith('comment '));
471+
.split('\n');
469472

470473
// decode header and build element and property list
471-
const { elements, format } = parseHeader(lines);
474+
const { elements, format, comments } = parseHeader(lines);
472475

473476
// check format is supported
474-
if (format !== 'binary_little_endian' && format !== 'binary_big_endian') {
477+
if (format !== 'binary_little_endian') {
475478
throw new Error('Unsupported ply format');
476479
}
477480

@@ -480,29 +483,36 @@ const readPly = async (reader, propertyFilter = null) => {
480483
streamBuf.head = headerLength + endHeaderBytes.length;
481484
streamBuf.compact();
482485

483-
// load compressed PLY with fast path
484-
if (isCompressedPly(elements)) {
485-
return await readCompressedPly(streamBuf, elements, format === 'binary_little_endian');
486-
}
486+
const readData = async () => {
487+
// load compressed PLY with fast path
488+
if (isCompressedPly(elements)) {
489+
return await readCompressedPly(streamBuf, elements);
490+
}
487491

488-
// allocate element storage
489-
elements.forEach((e) => {
490-
e.properties.forEach((p) => {
491-
const storageType = dataTypeMap.get(p.type);
492-
if (storageType) {
493-
const storage = (!propertyFilter || propertyFilter(p.name)) ? new storageType(e.count) : null;
494-
p.storage = storage;
495-
}
492+
// allocate element storage
493+
elements.forEach((e) => {
494+
e.properties.forEach((p) => {
495+
const storageType = dataTypeMap.get(p.type);
496+
if (storageType) {
497+
const storage = (!propertyFilter || propertyFilter(p.name)) ? new storageType(e.count) : null;
498+
p.storage = storage;
499+
}
500+
});
496501
});
497-
});
498502

499-
// load float32 PLY with fast path
500-
if (isFloatPly(elements)) {
501-
return await readFloatPly(streamBuf, elements, format === 'binary_little_endian');
502-
}
503+
// load float32 PLY with fast path
504+
if (isFloatPly(elements)) {
505+
return await readFloatPly(streamBuf, elements);
506+
}
503507

504-
// fallback, general case
505-
return await readGeneralPly(streamBuf, elements, format === 'binary_little_endian');
508+
// fallback, general case
509+
return await readGeneralPly(streamBuf, elements);
510+
};
511+
512+
return {
513+
data: await readData(),
514+
comments
515+
};
506516
};
507517

508518
// by default load everything
@@ -543,19 +553,20 @@ class PlyParser {
543553
if (!response || !response.body) {
544554
callback('Error loading resource', null);
545555
} else {
546-
const gsplatData = await readPly(response.body.getReader(), asset.data.elementFilter ?? defaultElementFilter);
556+
const { data, comments } = await readPly(response.body.getReader(), asset.data.elementFilter ?? defaultElementFilter);
547557

548558
// reorder data
549-
if (!gsplatData.isCompressed) {
559+
if (!data.isCompressed) {
550560
if (asset.data.reorder ?? true) {
551-
gsplatData.reorderData();
561+
data.reorderData();
552562
}
553563
}
554564

555565
// construct the resource
556566
const resource = new GSplatResource(
557567
this.device,
558-
gsplatData.isCompressed && asset.data.decompress ? gsplatData.decompress() : gsplatData
568+
data.isCompressed && asset.data.decompress ? data.decompress() : data,
569+
comments
559570
);
560571

561572
callback(null, resource);

0 commit comments

Comments
 (0)