()
| 79 | // this.elements will contain all the elements in the file, typically |
| 80 | // "vertex" contains the Gsplat data. |
| 81 | async parseHeader() { |
| 82 | const bufferStream = new ReadableStream({ |
| 83 | start: ( |
| 84 | controller: ReadableStreamController<Uint8Array<ArrayBuffer>>, |
| 85 | ) => { |
| 86 | // Assume the header is less than 64KB |
| 87 | controller.enqueue(this.fileBytes.slice(0, 65536)); |
| 88 | controller.close(); |
| 89 | }, |
| 90 | }); |
| 91 | const decoder = bufferStream |
| 92 | .pipeThrough(new TextDecoderStream()) |
| 93 | .getReader(); |
| 94 | |
| 95 | // Find the end of the text section of the PLY file |
| 96 | this.header = ""; |
| 97 | const headerTerminator = "end_header\n"; |
| 98 | while (true) { |
| 99 | const { value, done } = await decoder.read(); |
| 100 | if (done) { |
| 101 | throw new Error("Failed to read header"); |
| 102 | } |
| 103 | |
| 104 | this.header += value as string; |
| 105 | const endHeader = this.header.indexOf(headerTerminator); |
| 106 | if (endHeader >= 0) { |
| 107 | this.header = this.header.slice(0, endHeader + headerTerminator.length); |
| 108 | break; |
| 109 | } |
| 110 | } |
| 111 | // Partition the file into header and binary data |
| 112 | const headerLen = new TextEncoder().encode(this.header).length; |
| 113 | this.data = new DataView(this.fileBytes.buffer, headerLen); |
| 114 | |
| 115 | this.elements = {}; |
| 116 | let curElement: PlyElement | null = null; |
| 117 | this.comments = []; |
| 118 | |
| 119 | this.header |
| 120 | .trim() |
| 121 | .split("\n") |
| 122 | .forEach((line: string, lineIndex: number) => { |
| 123 | const trimmedLine = line.trim(); |
| 124 | if (lineIndex === 0) { |
| 125 | if (trimmedLine !== "ply") { |
| 126 | throw new Error("Invalid PLY header"); |
| 127 | } |
| 128 | return; |
| 129 | } |
| 130 | if (trimmedLine.length === 0) { |
| 131 | return; // Skip empty lines |
| 132 | } |
| 133 | |
| 134 | const fields = trimmedLine.split(" "); |
| 135 | switch (fields[0]) { |
| 136 | case "format": |
| 137 | if (fields[1] === "binary_little_endian") { |
| 138 | this.littleEndian = true; |
no test coverage detected