obj2gltf/lib/ArrayStorage.js
2019-02-05 22:03:42 -05:00

107 lines
3.2 KiB
JavaScript

'use strict';
const Cesium = require('cesium');
const ComponentDatatype = Cesium.ComponentDatatype;
module.exports = ArrayStorage;
const initialLength = 1024; // 2^10
const doublingThreshold = 33554432; // 2^25 (~134 MB for a Float32Array)
const fixedExpansionLength = 33554432; // 2^25 (~134 MB for a Float32Array)
/**
* Provides expandable typed array storage for geometry data. This is preferable to JS arrays which are
* stored with double precision. The resizing mechanism is similar to std::vector.
*
* @param {ComponentDatatype} componentDatatype The data type.
*
* @private
*/
function ArrayStorage(componentDatatype) {
this.componentDatatype = componentDatatype;
this.typedArray = ComponentDatatype.createTypedArray(componentDatatype, 0);
this.length = 0;
}
function resize(storage, length) {
const typedArray = ComponentDatatype.createTypedArray(storage.componentDatatype, length);
typedArray.set(storage.typedArray);
storage.typedArray = typedArray;
}
ArrayStorage.prototype.push = function(value) {
const length = this.length;
const typedArrayLength = this.typedArray.length;
if (length === 0) {
resize(this, initialLength);
} else if (length === typedArrayLength) {
if (length < doublingThreshold) {
resize(this, typedArrayLength * 2);
} else {
resize(this, typedArrayLength + fixedExpansionLength);
}
}
this.typedArray[this.length++] = value;
};
ArrayStorage.prototype.get = function(index) {
return this.typedArray[index];
};
const sizeOfUint16 = 2;
const sizeOfUint32 = 4;
const sizeOfFloat = 4;
ArrayStorage.prototype.toUint16Buffer = function() {
const length = this.length;
const typedArray = this.typedArray;
const paddedLength = length + ((length % 2 === 0) ? 0 : 1); // Round to next multiple of 2
const buffer = Buffer.alloc(paddedLength * sizeOfUint16);
for (let i = 0; i < length; ++i) {
buffer.writeUInt16LE(typedArray[i], i * sizeOfUint16);
}
return buffer;
};
ArrayStorage.prototype.toUint32Buffer = function() {
const length = this.length;
const typedArray = this.typedArray;
const buffer = Buffer.alloc(length * sizeOfUint32);
for (let i = 0; i < length; ++i) {
buffer.writeUInt32LE(typedArray[i], i * sizeOfUint32);
}
return buffer;
};
ArrayStorage.prototype.toFloatBuffer = function() {
const length = this.length;
const typedArray = this.typedArray;
const buffer = Buffer.alloc(length * sizeOfFloat);
for (let i = 0; i < length; ++i) {
buffer.writeFloatLE(typedArray[i], i * sizeOfFloat);
}
return buffer;
};
ArrayStorage.prototype.getMinMax = function(components) {
const length = this.length;
const typedArray = this.typedArray;
const count = length / components;
const min = new Array(components).fill(Number.POSITIVE_INFINITY);
const max = new Array(components).fill(Number.NEGATIVE_INFINITY);
for (let i = 0; i < count; ++i) {
for (let j = 0; j < components; ++j) {
const index = i * components + j;
const value = typedArray[index];
min[j] = Math.min(min[j], value);
max[j] = Math.max(max[j], value);
}
}
return {
min : min,
max : max
};
};