@blockv/threejs-to-v3d
Version:
Converts any format supported by ThreeJS to V3D.
198 lines (136 loc) • 3.97 kB
JavaScript
//
// BlobBuilder - Allows bytes to be written to the buffer without nowing the size first
const UTF8 = require('utf-8');
module.exports = class BlobBuilder {
constructor() {
// Properties
this.buffers = [];
this.bufferCapacity = 1 * 1024 * 1024;
this.currentBuffer = new Uint8Array(this.bufferCapacity);
this.currentBufferOffset = 0;
}
/** Add an unsigned byte */
addByte(b) {
// Make sure we have enough buffer
if (this.currentBufferOffset >= this.bufferCapacity) {
// Create new buffer
this.buffers.push(this.currentBuffer);
this.currentBuffer = new Uint8Array(this.bufferCapacity);
this.currentBufferOffset = 0;
}
// Write byte
this.currentBuffer[this.currentBufferOffset] = b;
this.currentBufferOffset += 1;
}
/** Add an unsigned integer */
addUInt8(num) {
this.addByte(num);
}
/** Add an unsigned integer */
addUInt16(num) {
// Create byte buffer
var bfr = new Uint8Array(2);
// Set data
new DataView(bfr.buffer).setUint16(0, num, true);
// Write bytes
for (var i = 0 ; i < bfr.length ; i++)
this.addByte(bfr[i]);
}
/** Add an unsigned integer */
addUInt32(num) {
// Create byte buffer
var bfr = new Uint8Array(4);
// Set data
new DataView(bfr.buffer).setUint32(0, num, true);
// Write bytes
for (var i = 0 ; i < bfr.length ; i++)
this.addByte(bfr[i]);
}
/** Add an unsigned integer */
addUInt64(num) {
// Create byte buffer
var bfr = new Uint8Array(4);
// Set data
new DataView(bfr.buffer).setUint32(0, num, true);
// Write bytes
for (var i = 0 ; i < bfr.length ; i++)
this.addByte(bfr[i]);
// Since we only support 32-bit integers, the rest is 0s
this.addByte(0);
this.addByte(0);
this.addByte(0);
this.addByte(0);
}
/** Add a float */
addFloat32(num) {
// Create byte buffer
var bfr = new Uint8Array(4);
// Set data
new DataView(bfr.buffer).setFloat32(0, num, true);
// Write bytes
for (var i = 0 ; i < bfr.length ; i++)
this.addByte(bfr[i]);
}
/** Add a null-terminated UTF-8 string */
addString(str, withTerminator) {
// Add bytes
var bytes = UTF8.setBytesFromString(str);
for (var byte of bytes)
this.addByte(byte);
// Add null terminator
if (withTerminator !== false)
this.addByte(0);
}
/** Add another blob builder's content */
addBlobBuilder(builder) {
// Add each byte of each existing buffer
for (var bfr of builder.buffers)
for (var i = 0 ; i < bfr.length ; i++)
this.addByte(bfr[i]);
// Add each byte of current buffer, up to filled point
for (var i = 0 ; i < builder.currentBufferOffset ; i++)
this.addByte(builder.currentBuffer[i]);
}
/** Add an array buffer of bytes */
addArrayBuffer(bfr) {
// Create bytes
var bfr = new Uint8Array(bfr);
for (var i = 0 ; i < bfr.length ; i++)
this.addByte(bfr[i]);
}
stringLengthInBytes(str, withTerminator) {
return UTF8.setBytesFromString(str).length + (withTerminator === false ? 0 : 1);
}
/** Build blob */
buildBlob(mimetype) {
// Add all buffers except the current one
var bfrs = this.buffers.slice();
// Add the used part of the last buffer
bfrs.push(this.currentBuffer.slice(0, this.currentBufferOffset));
// Create blob
return new Blob(bfrs, {type: mimetype});
}
/** Build ArrayBuffer */
buildArrayBuffer() {
// Create arraybuffer with required size
var bfr = new Uint8Array(this.buffers.length * this.bufferCapacity + this.currentBufferOffset);
var offset = 0;
// Copy full buffers
for (var b of this.buffers)
for (var i = 0 ; i < b.length ; i++)
bfr[offset++] = b[i];
// Copy incomplete buffer
for (var i = 0 ; i < this.currentBufferOffset ; i++)
bfr[offset++] = this.currentBuffer[i];
// Done
return bfr.buffer;
}
/** Get length of data */
get length() {
// Count filled buffers
var len = this.buffers.length * this.bufferCapacity;
// Add current buffer
len += this.currentBufferOffset;
return len;
}
}