Skip to content

Commit c0cfa23

Browse files
authored
glTF Exporter: Update GLB writing (#16820)
Trying to avoid using the Blob constructor with multiple parts, since that isn't implemented in the Blob polyfill for Native. Threw in some extras, including - Using DataWriter to neatly build our buffer - Bump up onExtensionExporting call before the binary is made
1 parent 3e53ade commit c0cfa23

File tree

1 file changed

+32
-39
lines changed

1 file changed

+32
-39
lines changed

packages/dev/serializers/src/glTF/2.0/glTFExporter.ts

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ import { GreasedLineBaseMesh } from "core/Meshes/GreasedLine/greasedLineBaseMesh
7878
import { Color3, Color4 } from "core/Maths/math.color";
7979
import { TargetCamera } from "core/Cameras/targetCamera";
8080
import { Epsilon } from "core/Maths/math.constants";
81+
import { DataWriter } from "./dataWriter";
8182

8283
class ExporterState {
8384
// Babylon indices array, start, count, offset, flip -> glTF accessor index
@@ -521,9 +522,9 @@ export class GLTFExporter {
521522

522523
public async generateGLTFAsync(glTFPrefix: string): Promise<GLTFData> {
523524
const binaryBuffer = await this._generateBinaryAsync();
524-
525525
this._extensionsOnExporting();
526526
const jsonText = this._generateJSON(binaryBuffer.byteLength, glTFPrefix, true);
527+
527528
const bin = new Blob([binaryBuffer], { type: "application/octet-stream" });
528529

529530
const glTFFileName = glTFPrefix + ".gltf";
@@ -564,15 +565,15 @@ export class GLTFExporter {
564565
public async generateGLBAsync(glTFPrefix: string): Promise<GLTFData> {
565566
this._shouldUseGlb = true;
566567
const binaryBuffer = await this._generateBinaryAsync();
567-
568568
this._extensionsOnExporting();
569569
const jsonText = this._generateJSON(binaryBuffer.byteLength);
570+
570571
const glbFileName = glTFPrefix + ".glb";
571572
const headerLength = 12;
572573
const chunkLengthPrefix = 8;
573574
let jsonLength = jsonText.length;
574575
let encodedJsonText;
575-
// make use of TextEncoder when available
576+
// Make use of TextEncoder when available
576577
if (typeof TextEncoder !== "undefined") {
577578
const encoder = new TextEncoder();
578579
encodedJsonText = encoder.encode(jsonText);
@@ -583,61 +584,53 @@ export class GLTFExporter {
583584

584585
const byteLength = headerLength + 2 * chunkLengthPrefix + jsonLength + jsonPadding + binaryBuffer.byteLength + binPadding;
585586

586-
// header
587-
const headerBuffer = new ArrayBuffer(headerLength);
588-
const headerBufferView = new DataView(headerBuffer);
589-
headerBufferView.setUint32(0, 0x46546c67, true); //glTF
590-
headerBufferView.setUint32(4, 2, true); // version
591-
headerBufferView.setUint32(8, byteLength, true); // total bytes in file
592-
593-
// json chunk
594-
const jsonChunkBuffer = new ArrayBuffer(chunkLengthPrefix + jsonLength + jsonPadding);
595-
const jsonChunkBufferView = new DataView(jsonChunkBuffer);
596-
jsonChunkBufferView.setUint32(0, jsonLength + jsonPadding, true);
597-
jsonChunkBufferView.setUint32(4, 0x4e4f534a, true);
598-
599-
// json chunk bytes
600-
const jsonData = new Uint8Array(jsonChunkBuffer, chunkLengthPrefix);
601-
// if TextEncoder was available, we can simply copy the encoded array
587+
const dataWriter = new DataWriter(byteLength);
588+
589+
// Header
590+
dataWriter.writeUInt32(0x46546c67); // "glTF"
591+
dataWriter.writeUInt32(2); // Version
592+
dataWriter.writeUInt32(byteLength); // Total bytes in file
593+
594+
// JSON chunk length prefix
595+
dataWriter.writeUInt32(jsonLength + jsonPadding);
596+
dataWriter.writeUInt32(0x4e4f534a); // "JSON"
597+
598+
// JSON chunk bytes
602599
if (encodedJsonText) {
603-
jsonData.set(encodedJsonText);
600+
// If TextEncoder was available, we can simply copy the encoded array
601+
dataWriter.writeTypedArray(encodedJsonText);
604602
} else {
605603
const blankCharCode = "_".charCodeAt(0);
606604
for (let i = 0; i < jsonLength; ++i) {
607605
const charCode = jsonText.charCodeAt(i);
608-
// if the character doesn't fit into a single UTF-16 code unit, just put a blank character
606+
// If the character doesn't fit into a single UTF-16 code unit, just put a blank character
609607
if (charCode != jsonText.codePointAt(i)) {
610-
jsonData[i] = blankCharCode;
608+
dataWriter.writeUInt8(blankCharCode);
611609
} else {
612-
jsonData[i] = charCode;
610+
dataWriter.writeUInt8(charCode);
613611
}
614612
}
615613
}
616614

617-
// json padding
618-
const jsonPaddingView = new Uint8Array(jsonChunkBuffer, chunkLengthPrefix + jsonLength);
615+
// JSON padding
619616
for (let i = 0; i < jsonPadding; ++i) {
620-
jsonPaddingView[i] = 0x20;
617+
dataWriter.writeUInt8(0x20);
621618
}
622619

623-
// binary chunk
624-
const binaryChunkBuffer = new ArrayBuffer(chunkLengthPrefix);
625-
const binaryChunkBufferView = new DataView(binaryChunkBuffer);
626-
binaryChunkBufferView.setUint32(0, binaryBuffer.byteLength + binPadding, true);
627-
binaryChunkBufferView.setUint32(4, 0x004e4942, true);
620+
// Binary chunk length prefix
621+
dataWriter.writeUInt32(binaryBuffer.byteLength + binPadding);
622+
dataWriter.writeUInt32(0x004e4942); // "BIN"
628623

629-
// binary padding
630-
const binPaddingBuffer = new ArrayBuffer(binPadding);
631-
const binPaddingView = new Uint8Array(binPaddingBuffer);
624+
// Binary chunk bytes
625+
dataWriter.writeTypedArray(binaryBuffer);
626+
627+
// Binary padding
632628
for (let i = 0; i < binPadding; ++i) {
633-
binPaddingView[i] = 0;
629+
dataWriter.writeUInt8(0);
634630
}
635631

636-
const glbData = [headerBuffer, jsonChunkBuffer, binaryChunkBuffer, binaryBuffer, binPaddingBuffer];
637-
const glbFile = new Blob(glbData, { type: "application/octet-stream" });
638-
639632
const container = new GLTFData();
640-
container.files[glbFileName] = glbFile;
633+
container.files[glbFileName] = new Blob([dataWriter.getOutputData()], { type: "application/octet-stream" });
641634

642635
return container;
643636
}

0 commit comments

Comments
 (0)