@@ -162,12 +162,16 @@ class StreamBuf {
162
162
// string containing the ply format
163
163
const parseHeader = ( lines ) => {
164
164
const elements = [ ] ;
165
+ const comments = [ ] ;
165
166
let format ;
166
167
167
168
for ( let i = 1 ; i < lines . length ; ++ i ) {
168
169
const words = lines [ i ] . split ( ' ' ) ;
169
170
170
171
switch ( words [ 0 ] ) {
172
+ case 'comment' :
173
+ comments . push ( words . slice ( 1 ) . join ( ' ' ) ) ;
174
+ break ;
171
175
case 'format' :
172
176
format = words [ 1 ] ;
173
177
break ;
@@ -196,7 +200,7 @@ const parseHeader = (lines) => {
196
200
}
197
201
}
198
202
199
- return { elements, format } ;
203
+ return { elements, format, comments } ;
200
204
} ;
201
205
202
206
// return true if the array of elements references a compressed ply file
@@ -239,7 +243,7 @@ const isFloatPly = (elements) => {
239
243
} ;
240
244
241
245
// read the data of a compressed ply file
242
- const readCompressedPly = async ( streamBuf , elements , littleEndian ) => {
246
+ const readCompressedPly = async ( streamBuf , elements ) => {
243
247
const result = new GSplatCompressedData ( ) ;
244
248
245
249
const numChunks = elements [ 0 ] . count ;
@@ -294,7 +298,7 @@ const readCompressedPly = async (streamBuf, elements, littleEndian) => {
294
298
} ;
295
299
296
300
// read the data of a floating point ply file
297
- const readFloatPly = async ( streamBuf , elements , littleEndian ) => {
301
+ const readFloatPly = async ( streamBuf , elements ) => {
298
302
// calculate the size of an input element record
299
303
const element = elements [ 0 ] ;
300
304
const properties = element . properties ;
@@ -336,7 +340,7 @@ const readFloatPly = async (streamBuf, elements, littleEndian) => {
336
340
return new GSplatData ( elements ) ;
337
341
} ;
338
342
339
- const readGeneralPly = async ( streamBuf , elements , littleEndian ) => {
343
+ const readGeneralPly = async ( streamBuf , elements ) => {
340
344
// read and deinterleave the data
341
345
for ( let i = 0 ; i < elements . length ; ++ i ) {
342
346
const element = elements [ i ] ;
@@ -391,7 +395,7 @@ const readGeneralPly = async (streamBuf, elements, littleEndian) => {
391
395
*
392
396
* @param {ReadableStreamDefaultReader<Uint8Array> } reader - The reader.
393
397
* @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.
395
399
*/
396
400
const readPly = async ( reader , propertyFilter = null ) => {
397
401
/**
@@ -464,14 +468,13 @@ const readPly = async (reader, propertyFilter = null) => {
464
468
// decode buffer header text and split into lines and remove comments
465
469
const lines = new TextDecoder ( 'ascii' )
466
470
. decode ( streamBuf . data . subarray ( 0 , headerLength ) )
467
- . split ( '\n' )
468
- . filter ( line => ! line . startsWith ( 'comment ' ) ) ;
471
+ . split ( '\n' ) ;
469
472
470
473
// decode header and build element and property list
471
- const { elements, format } = parseHeader ( lines ) ;
474
+ const { elements, format, comments } = parseHeader ( lines ) ;
472
475
473
476
// check format is supported
474
- if ( format !== 'binary_little_endian' && format !== 'binary_big_endian' ) {
477
+ if ( format !== 'binary_little_endian' ) {
475
478
throw new Error ( 'Unsupported ply format' ) ;
476
479
}
477
480
@@ -480,29 +483,36 @@ const readPly = async (reader, propertyFilter = null) => {
480
483
streamBuf . head = headerLength + endHeaderBytes . length ;
481
484
streamBuf . compact ( ) ;
482
485
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
+ }
487
491
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
+ } ) ;
496
501
} ) ;
497
- } ) ;
498
502
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
+ }
503
507
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
+ } ;
506
516
} ;
507
517
508
518
// by default load everything
@@ -543,19 +553,20 @@ class PlyParser {
543
553
if ( ! response || ! response . body ) {
544
554
callback ( 'Error loading resource' , null ) ;
545
555
} 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 ) ;
547
557
548
558
// reorder data
549
- if ( ! gsplatData . isCompressed ) {
559
+ if ( ! data . isCompressed ) {
550
560
if ( asset . data . reorder ?? true ) {
551
- gsplatData . reorderData ( ) ;
561
+ data . reorderData ( ) ;
552
562
}
553
563
}
554
564
555
565
// construct the resource
556
566
const resource = new GSplatResource (
557
567
this . device ,
558
- gsplatData . isCompressed && asset . data . decompress ? gsplatData . decompress ( ) : gsplatData
568
+ data . isCompressed && asset . data . decompress ? data . decompress ( ) : data ,
569
+ comments
559
570
) ;
560
571
561
572
callback ( null , resource ) ;
0 commit comments