@gltf-transform/core
Advanced tools
Comparing version 0.0.14 to 0.1.0
@@ -5,3 +5,3 @@ 'use strict'; | ||
var AccessorType = { | ||
const AccessorType = { | ||
SCALAR: 'SCALAR', | ||
@@ -15,3 +15,3 @@ VEC2: 'VEC2', | ||
}; | ||
var AccessorTypeData = { | ||
const AccessorTypeData = { | ||
SCALAR: { value: 'SCALAR', size: 1 }, | ||
@@ -25,3 +25,3 @@ VEC2: { value: 'VEC2', size: 2 }, | ||
}; | ||
var AccessorComponentType = { | ||
const AccessorComponentType = { | ||
BYTE: 5120, | ||
@@ -34,3 +34,3 @@ UNSIGNED_BYTE: 5121, | ||
}; | ||
var AccessorComponentTypeData = { | ||
const AccessorComponentTypeData = { | ||
'5120': { value: 'BYTE', size: 1 }, | ||
@@ -43,3 +43,3 @@ '5121': { value: 'UNSIGNED_BYTE', size: 1 }, | ||
}; | ||
var BufferViewTarget = { | ||
const BufferViewTarget = { | ||
ARRAY_BUFFER: 34962, | ||
@@ -52,4 +52,4 @@ ELEMENT_ARRAY_BUFFER: 34963 | ||
*/ | ||
var GLTFContainer = /** @class */ (function () { | ||
function GLTFContainer(json, resources) { | ||
class GLTFContainer { | ||
constructor(json, resources) { | ||
this.json = json; | ||
@@ -62,41 +62,41 @@ this.resources = resources; | ||
*/ | ||
GLTFContainer.prototype.resolveURI = function (uri) { | ||
resolveURI(uri) { | ||
return this.resources[uri]; | ||
}; | ||
GLTFContainer.prototype.getBuffer = function (bufferIndex) { | ||
} | ||
getBuffer(bufferIndex) { | ||
return this.resolveURI(this.json.buffers[bufferIndex].uri); | ||
}; | ||
GLTFContainer.prototype.setBuffer = function (bufferIndex, buffer) { | ||
} | ||
setBuffer(bufferIndex, buffer) { | ||
this.resources[this.json.buffers[bufferIndex].uri] = buffer; | ||
}; | ||
} | ||
/** | ||
* Creates a deep copy of the asset. | ||
*/ | ||
GLTFContainer.prototype.clone = function () { | ||
var json = JSON.parse(JSON.stringify(this.json)); | ||
var resources = {}; | ||
for (var uri in this.resources) { | ||
var resource = this.resolveURI(uri); | ||
clone() { | ||
const json = JSON.parse(JSON.stringify(this.json)); | ||
const resources = {}; | ||
for (const uri in this.resources) { | ||
const resource = this.resolveURI(uri); | ||
resources[uri] = resource.slice(0); | ||
} | ||
return new GLTFContainer(json, resources); | ||
}; | ||
GLTFContainer.prototype.validate = function () { | ||
} | ||
validate() { | ||
if (this.json.buffers.length > 1) { | ||
throw new Error("Expected one buffer, found " + this.json.buffers.length + "."); | ||
throw new Error(`Expected one buffer, found ${this.json.buffers.length}.`); | ||
} | ||
var embeddedImages = (this.json.images || []).filter(function (image) { return image.bufferView !== undefined; }); | ||
const embeddedImages = (this.json.images || []).filter((image) => image.bufferView !== undefined); | ||
if (embeddedImages.length) { | ||
throw new Error("Expected only external images, found " + embeddedImages.length + " embedded."); | ||
throw new Error(`Expected only external images, found ${embeddedImages.length} embedded.`); | ||
} | ||
var embeddedBuffers = this.json.buffers.filter(function (buffer) { return buffer.uri === undefined; }); | ||
const embeddedBuffers = this.json.buffers.filter((buffer) => buffer.uri === undefined); | ||
if (embeddedBuffers.length) { | ||
throw new Error("Expected exactly one buffer, which should be external, and found " + embeddedBuffers.length + " embedded."); | ||
throw new Error(`Expected exactly one buffer, which should be external, and found ${embeddedBuffers.length} embedded.`); | ||
} | ||
for (var key in this.json) { | ||
if (Array.isArray(this.json[key]) && this.json[key].length === 0) { | ||
throw new Error("Empty top-level array, \"" + this.json[key] + "\"."); | ||
throw new Error(`Empty top-level array, "${this.json[key]}".`); | ||
} | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -106,9 +106,9 @@ * Returns the accessor for the given index, as a typed array. | ||
*/ | ||
GLTFContainer.prototype.getAccessorArray = function (index) { | ||
var accessor = this.json.accessors[index]; | ||
var bufferView = this.json.bufferViews[accessor.bufferView]; | ||
var buffer = this.json.buffers[bufferView.buffer]; | ||
var resource = this.resources[buffer.uri]; | ||
var valueSize = AccessorTypeData[accessor.type].size; | ||
var start = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0); | ||
getAccessorArray(index) { | ||
const accessor = this.json.accessors[index]; | ||
const bufferView = this.json.bufferViews[accessor.bufferView]; | ||
const buffer = this.json.buffers[bufferView.buffer]; | ||
const resource = this.resources[buffer.uri]; | ||
const valueSize = AccessorTypeData[accessor.type].size; | ||
const start = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0); | ||
switch (accessor.componentType) { | ||
@@ -124,6 +124,6 @@ case AccessorComponentType.FLOAT: | ||
default: | ||
throw new Error("Accessor componentType " + accessor.componentType + " not implemented."); | ||
throw new Error(`Accessor componentType ${accessor.componentType} not implemented.`); | ||
} | ||
}; | ||
GLTFContainer.prototype.equals = function (other) { | ||
} | ||
equals(other) { | ||
if (JSON.stringify(this.json) !== JSON.stringify(other.json)) | ||
@@ -133,5 +133,5 @@ return false; | ||
return false; | ||
for (var resourceName in this.resources) { | ||
var resource = Buffer.from(this.resources[resourceName]); | ||
var otherResource = Buffer.from(other.resources[resourceName]); | ||
for (const resourceName in this.resources) { | ||
const resource = Buffer.from(this.resources[resourceName]); | ||
const otherResource = Buffer.from(other.resources[resourceName]); | ||
if (!resource.equals(otherResource)) | ||
@@ -141,5 +141,4 @@ return false; | ||
return true; | ||
}; | ||
return GLTFContainer; | ||
}()); | ||
} | ||
} | ||
@@ -155,4 +154,4 @@ (function (LoggerVerbosity) { | ||
*/ | ||
var Logger = /** @class */ (function () { | ||
function Logger(name, verbosity) { | ||
class Logger { | ||
constructor(name, verbosity) { | ||
this.name = name; | ||
@@ -165,7 +164,7 @@ this.verbosity = verbosity; | ||
*/ | ||
Logger.prototype.info = function (text) { | ||
info(text) { | ||
if (this.verbosity <= exports.LoggerVerbosity.INFO) { | ||
console.log(this.name + ": " + text); | ||
console.log(`${this.name}: ${text}`); | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -175,7 +174,7 @@ * Logs at level WARNING. | ||
*/ | ||
Logger.prototype.warn = function (text) { | ||
warn(text) { | ||
if (this.verbosity <= exports.LoggerVerbosity.WARNING) { | ||
console.warn(this.name + ": " + text); | ||
console.warn(`${this.name}: ${text}`); | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -185,16 +184,15 @@ * Logs at level ERROR. | ||
*/ | ||
Logger.prototype.error = function (text) { | ||
error(text) { | ||
if (this.verbosity <= exports.LoggerVerbosity.ERROR) { | ||
console.error(this.name + ": " + text); | ||
console.error(`${this.name}: ${text}`); | ||
} | ||
}; | ||
return Logger; | ||
}()); | ||
} | ||
} | ||
var PackedGLTFContainer = /** @class */ (function () { | ||
function PackedGLTFContainer(json, buffer) { | ||
class PackedGLTFContainer { | ||
constructor(json, buffer) { | ||
this.json = json; | ||
this.buffer = buffer; | ||
} | ||
PackedGLTFContainer.prototype.getBuffer = function (bufferIndex) { | ||
getBuffer(bufferIndex) { | ||
if (bufferIndex !== 0) { | ||
@@ -204,4 +202,4 @@ throw new Error('Invalid buffer index.'); | ||
return this.buffer; | ||
}; | ||
PackedGLTFContainer.prototype.setBuffer = function (bufferIndex, buffer) { | ||
} | ||
setBuffer(bufferIndex, buffer) { | ||
if (bufferIndex !== 0) { | ||
@@ -211,9 +209,9 @@ throw new Error('Invalid buffer index.'); | ||
this.buffer = buffer; | ||
}; | ||
PackedGLTFContainer.prototype.validate = function () { | ||
} | ||
validate() { | ||
if (this.json.buffers.length > 1) { | ||
throw new Error("Expected 1 buffer, found " + this.json.buffers.length + "."); | ||
throw new Error(`Expected 1 buffer, found ${this.json.buffers.length}.`); | ||
} | ||
var externalImages = (this.json.images || []).filter(function (image) { return image.uri !== undefined; }); | ||
var externalBuffers = this.json.buffers.filter(function (buffer) { return buffer.uri !== undefined; }); | ||
const externalImages = (this.json.images || []).filter((image) => image.uri !== undefined); | ||
const externalBuffers = this.json.buffers.filter((buffer) => buffer.uri !== undefined); | ||
if (externalImages.length || externalBuffers.length) { | ||
@@ -224,15 +222,15 @@ throw new Error('Found external resource references.'); | ||
if (Array.isArray(this.json[key]) && this.json[key].length === 0) { | ||
throw new Error("Empty top-level array, \"" + this.json[key] + "\"."); | ||
throw new Error(`Empty top-level array, "${this.json[key]}".`); | ||
} | ||
} | ||
}; | ||
PackedGLTFContainer.pack = function (container) { | ||
} | ||
static pack(container) { | ||
container.validate(); | ||
container = container.clone(); | ||
var json = container.json; | ||
var buffer = container.resolveURI(container.json.buffers[0].uri); | ||
const json = container.json; | ||
const buffer = container.resolveURI(container.json.buffers[0].uri); | ||
delete json.buffers[0].uri; | ||
var packedContainer = new PackedGLTFContainer(json, buffer); | ||
(json.images || []).forEach(function (image) { | ||
var imageData = container.resolveURI(image.uri); | ||
const packedContainer = new PackedGLTFContainer(json, buffer); | ||
(json.images || []).forEach((image) => { | ||
const imageData = container.resolveURI(image.uri); | ||
delete image.uri; | ||
@@ -244,18 +242,17 @@ GLTFUtil.addBufferView(packedContainer, imageData, 0); | ||
return packedContainer; | ||
}; | ||
PackedGLTFContainer.prototype.unpack = function () { | ||
var _this = this; | ||
var json = JSON.parse(JSON.stringify(this.json)); | ||
var buffer = this.buffer.slice(0); | ||
var resources = { 'resources.bin': buffer }; | ||
} | ||
unpack() { | ||
const json = JSON.parse(JSON.stringify(this.json)); | ||
let buffer = this.buffer.slice(0); | ||
const resources = { 'resources.bin': buffer }; | ||
json.buffers[0].uri = 'resources.bin'; | ||
var container = new GLTFContainer(json, resources); | ||
(json.images || []).forEach(function (image, imageIndex) { | ||
var bufferViewIndex = image.bufferView; | ||
var bufferView = json.bufferViews[bufferViewIndex]; | ||
const container = new GLTFContainer(json, resources); | ||
(json.images || []).forEach((image, imageIndex) => { | ||
const bufferViewIndex = image.bufferView; | ||
const bufferView = json.bufferViews[bufferViewIndex]; | ||
delete image.bufferView; | ||
var imageData = _this.buffer.slice(bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength); | ||
GLTFUtil.removeBufferView(_this, bufferViewIndex); | ||
var extension = image.mimeType === 'image/jpeg' ? 'jpg' : 'png'; | ||
image.uri = image.name ? image.name.replace(/\.\w+$/, '') + ("." + extension) : "image-" + imageIndex + "." + extension; | ||
const imageData = this.buffer.slice(bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength); | ||
GLTFUtil.removeBufferView(this, bufferViewIndex); | ||
const extension = image.mimeType === 'image/jpeg' ? 'jpg' : 'png'; | ||
image.uri = image.name ? image.name.replace(/\.\w+$/, '') + `.${extension}` : `image-${imageIndex}.${extension}`; | ||
resources[image.uri] = imageData; | ||
@@ -265,5 +262,4 @@ }); | ||
return container; | ||
}; | ||
return PackedGLTFContainer; | ||
}()); | ||
} | ||
} | ||
@@ -326,5 +322,3 @@ //////////////////////////////////////////////////////// | ||
*/ | ||
var GLTFUtil = /** @class */ (function () { | ||
function GLTFUtil() { | ||
} | ||
class GLTFUtil { | ||
/** | ||
@@ -335,5 +329,5 @@ * Creates a GLTFContainer from the given JSON and files. | ||
*/ | ||
GLTFUtil.fromGLTF = function (json, resources) { | ||
static fromGLTF(json, resources) { | ||
return new GLTFContainer(json, resources); | ||
}; | ||
} | ||
/** | ||
@@ -343,5 +337,5 @@ * Creates a GLTFContainer from the given GLB binary. | ||
*/ | ||
GLTFUtil.fromGLB = function (glb) { | ||
static fromGLB(glb) { | ||
// Decode and verify GLB header. | ||
var header = new Uint32Array(glb, 0, 3); | ||
const header = new Uint32Array(glb, 0, 3); | ||
if (header[0] !== 0x46546C67) { | ||
@@ -351,9 +345,9 @@ throw new Error('Invalid glTF asset.'); | ||
else if (header[1] !== 2) { | ||
throw new Error("Unsupported glTF binary version, \"" + header[1] + "\"."); | ||
throw new Error(`Unsupported glTF binary version, "${header[1]}".`); | ||
} | ||
// Decode and verify chunk headers. | ||
var jsonChunkHeader = new Uint32Array(glb, 12, 2); | ||
var jsonByteOffset = 20; | ||
var jsonByteLength = jsonChunkHeader[0]; | ||
var binaryChunkHeader = new Uint32Array(glb, jsonByteOffset + jsonByteLength, 2); | ||
const jsonChunkHeader = new Uint32Array(glb, 12, 2); | ||
const jsonByteOffset = 20; | ||
const jsonByteLength = jsonChunkHeader[0]; | ||
const binaryChunkHeader = new Uint32Array(glb, jsonByteOffset + jsonByteLength, 2); | ||
if (jsonChunkHeader[1] !== 0x4E4F534A || binaryChunkHeader[1] !== 0x004E4942) { | ||
@@ -363,9 +357,9 @@ throw new Error('Unexpected GLB layout.'); | ||
// Decode content. | ||
var jsonText = this.decodeText(glb.slice(jsonByteOffset, jsonByteOffset + jsonByteLength)); | ||
var json = JSON.parse(jsonText); | ||
var binaryByteOffset = jsonByteOffset + jsonByteLength + 8; | ||
var binaryByteLength = binaryChunkHeader[0]; | ||
var binary = glb.slice(binaryByteOffset, binaryByteOffset + binaryByteLength); | ||
const jsonText = this.decodeText(glb.slice(jsonByteOffset, jsonByteOffset + jsonByteLength)); | ||
const json = JSON.parse(jsonText); | ||
const binaryByteOffset = jsonByteOffset + jsonByteLength + 8; | ||
const binaryByteLength = binaryChunkHeader[0]; | ||
const binary = glb.slice(binaryByteOffset, binaryByteOffset + binaryByteLength); | ||
return new PackedGLTFContainer(json, binary).unpack(); | ||
}; | ||
} | ||
/** | ||
@@ -375,6 +369,6 @@ * Serializes a GLTFContainer to GLTF JSON and external files. | ||
*/ | ||
GLTFUtil.toGLTF = function (container) { | ||
var json = container.json, resources = container.resources; | ||
return { json: json, resources: resources }; | ||
}; | ||
static toGLTF(container) { | ||
const { json, resources } = container; | ||
return { json, resources }; | ||
} | ||
/** | ||
@@ -384,16 +378,16 @@ * Serializes a GLTFContainer to a GLB binary. | ||
*/ | ||
GLTFUtil.toGLB = function (container) { | ||
static toGLB(container) { | ||
if (container instanceof GLTFContainer) { | ||
container = PackedGLTFContainer.pack(container); | ||
} | ||
var jsonText = JSON.stringify(container.json); | ||
var jsonChunkData = this.pad(GLTFUtil.encodeText(jsonText), 0x20); | ||
var jsonChunkHeader = new Uint32Array([jsonChunkData.byteLength, 0x4E4F534A]).buffer; | ||
var jsonChunk = this.join(jsonChunkHeader, jsonChunkData); | ||
var binaryChunkData = this.pad(container.getBuffer(0), 0x00); | ||
var binaryChunkHeader = new Uint32Array([binaryChunkData.byteLength, 0x004E4942]).buffer; | ||
var binaryChunk = this.join(binaryChunkHeader, binaryChunkData); | ||
var header = new Uint32Array([0x46546C67, 2, 12 + jsonChunk.byteLength + binaryChunk.byteLength]).buffer; | ||
const jsonText = JSON.stringify(container.json); | ||
const jsonChunkData = this.pad(GLTFUtil.encodeText(jsonText), 0x20); | ||
const jsonChunkHeader = new Uint32Array([jsonChunkData.byteLength, 0x4E4F534A]).buffer; | ||
const jsonChunk = this.join(jsonChunkHeader, jsonChunkData); | ||
const binaryChunkData = this.pad(container.getBuffer(0), 0x00); | ||
const binaryChunkHeader = new Uint32Array([binaryChunkData.byteLength, 0x004E4942]).buffer; | ||
const binaryChunk = this.join(binaryChunkHeader, binaryChunkData); | ||
const header = new Uint32Array([0x46546C67, 2, 12 + jsonChunk.byteLength + binaryChunk.byteLength]).buffer; | ||
return this.join(this.join(header, jsonChunk), binaryChunk); | ||
}; | ||
} | ||
/** | ||
@@ -403,8 +397,8 @@ * Creates a buffer from a Data URI. | ||
*/ | ||
GLTFUtil.createBufferFromDataURI = function (dataURI) { | ||
static createBufferFromDataURI(dataURI) { | ||
if (typeof Buffer === 'undefined') { | ||
// Browser. | ||
var byteString = atob(dataURI.split(',')[1]); | ||
var ia = new Uint8Array(byteString.length); | ||
for (var i = 0; i < byteString.length; i++) { | ||
const byteString = atob(dataURI.split(',')[1]); | ||
const ia = new Uint8Array(byteString.length); | ||
for (let i = 0; i < byteString.length; i++) { | ||
ia[i] = byteString.charCodeAt(i); | ||
@@ -418,7 +412,7 @@ } | ||
} | ||
}; | ||
GLTFUtil.createLogger = function (name, verbosity) { | ||
} | ||
static createLogger(name, verbosity) { | ||
return new Logger(name, verbosity); | ||
}; | ||
GLTFUtil.encodeText = function (text) { | ||
} | ||
static encodeText(text) { | ||
if (typeof TextEncoder !== 'undefined') { | ||
@@ -428,17 +422,16 @@ return new TextEncoder().encode(text).buffer; | ||
return this.trimBuffer(Buffer.from(text)); | ||
}; | ||
GLTFUtil.decodeText = function (buffer) { | ||
} | ||
static decodeText(buffer) { | ||
if (typeof TextDecoder !== 'undefined') { | ||
return new TextDecoder().decode(buffer); | ||
} | ||
var a = Buffer.from(buffer); | ||
const a = Buffer.from(buffer); | ||
return a.toString('utf8'); | ||
}; | ||
GLTFUtil.trimBuffer = function (buffer) { | ||
var byteOffset = buffer.byteOffset, byteLength = buffer.byteLength; | ||
} | ||
static trimBuffer(buffer) { | ||
const { byteOffset, byteLength } = buffer; | ||
return buffer.buffer.slice(byteOffset, byteOffset + byteLength); | ||
}; | ||
GLTFUtil.analyze = function (container) { | ||
var _this = this; | ||
var report = { | ||
} | ||
static analyze(container) { | ||
const report = { | ||
meshes: (container.json.meshes || []).length, | ||
@@ -459,16 +452,16 @@ textures: (container.json.textures || []).length, | ||
// Primitives and targets. | ||
(container.json.meshes || []).forEach(function (mesh) { | ||
(container.json.meshes || []).forEach((mesh) => { | ||
report.primitives += mesh.primitives.length; | ||
mesh.primitives.forEach(function (primitive) { | ||
mesh.primitives.forEach((primitive) => { | ||
if (primitive.indices !== undefined) { | ||
report.dataUsage.geometry += _this.getAccessorByteLength(container.json.accessors[primitive.indices]); | ||
report.dataUsage.geometry += this.getAccessorByteLength(container.json.accessors[primitive.indices]); | ||
} | ||
Object.keys(primitive.attributes).forEach(function (attr) { | ||
var accessor = container.json.accessors[primitive.attributes[attr]]; | ||
report.dataUsage.geometry += _this.getAccessorByteLength(accessor); | ||
Object.keys(primitive.attributes).forEach((attr) => { | ||
const accessor = container.json.accessors[primitive.attributes[attr]]; | ||
report.dataUsage.geometry += this.getAccessorByteLength(accessor); | ||
}); | ||
(primitive.targets || []).forEach(function (target) { | ||
Object.keys(target).forEach(function (attr) { | ||
var accessor = container.json.accessors[target[attr]]; | ||
report.dataUsage.targets += _this.getAccessorByteLength(accessor); | ||
(primitive.targets || []).forEach((target) => { | ||
Object.keys(target).forEach((attr) => { | ||
const accessor = container.json.accessors[target[attr]]; | ||
report.dataUsage.targets += this.getAccessorByteLength(accessor); | ||
}); | ||
@@ -479,12 +472,12 @@ }); | ||
// Animation | ||
(container.json.animations || []).forEach(function (animation) { | ||
animation.samplers.forEach(function (sampler) { | ||
var input = container.json.accessors[sampler.input]; | ||
var output = container.json.accessors[sampler.output]; | ||
report.dataUsage.animation += _this.getAccessorByteLength(input); | ||
report.dataUsage.animation += _this.getAccessorByteLength(output); | ||
(container.json.animations || []).forEach((animation) => { | ||
animation.samplers.forEach((sampler) => { | ||
const input = container.json.accessors[sampler.input]; | ||
const output = container.json.accessors[sampler.output]; | ||
report.dataUsage.animation += this.getAccessorByteLength(input); | ||
report.dataUsage.animation += this.getAccessorByteLength(output); | ||
}); | ||
}); | ||
// Textures | ||
(container.json.images || []).forEach(function (image) { | ||
(container.json.images || []).forEach((image) => { | ||
if (image.uri !== undefined) { | ||
@@ -500,3 +493,3 @@ report.dataUsage.textures += container.resolveURI(image.uri).byteLength; | ||
return report; | ||
}; | ||
} | ||
/** | ||
@@ -509,21 +502,21 @@ * Adds a new image to the glTF container. | ||
*/ | ||
GLTFUtil.addImage = function (container, name, file, type) { | ||
var uri, mimeType; | ||
static addImage(container, name, file, type) { | ||
let uri, mimeType; | ||
switch (type) { | ||
case 'image/jpeg': | ||
uri = name + ".jpg"; | ||
uri = `${name}.jpg`; | ||
mimeType = 'image/jpeg'; | ||
break; | ||
case 'image/png': | ||
uri = name + ".png"; | ||
uri = `${name}.png`; | ||
mimeType = 'image/png'; | ||
break; | ||
default: | ||
throw new Error("Unsupported image type, \"" + type + "\"."); | ||
throw new Error(`Unsupported image type, "${type}".`); | ||
} | ||
container.json.images = container.json.images || []; | ||
container.json.images.push({ name: name, mimeType: mimeType, uri: uri }); | ||
container.json.images.push({ name, mimeType, uri }); | ||
container.resources[uri] = file; | ||
return container; | ||
}; | ||
} | ||
/** | ||
@@ -534,9 +527,9 @@ * Removes an image from the glTF container. Fails if image is still in use. | ||
*/ | ||
GLTFUtil.removeImage = function (container, index) { | ||
var textures = container.json.textures.filter(function (texture) { return texture.source === index; }); | ||
static removeImage(container, index) { | ||
const textures = container.json.textures.filter((texture) => texture.source === index); | ||
if (textures.length) { | ||
throw new Error("Image is in use by " + textures.length + " textures and cannot be removed."); | ||
throw new Error(`Image is in use by ${textures.length} textures and cannot be removed.`); | ||
} | ||
var image = container.json.images[index]; | ||
var imageBuffer = container.resolveURI(image.uri); | ||
const image = container.json.images[index]; | ||
const imageBuffer = container.resolveURI(image.uri); | ||
if (!imageBuffer) { | ||
@@ -546,3 +539,3 @@ throw new Error('No such image, or image is embedded.'); | ||
container.json.images.splice(index, 1); | ||
container.json.textures.forEach(function (texture) { | ||
container.json.textures.forEach((texture) => { | ||
if (texture.source > index) | ||
@@ -553,6 +546,6 @@ texture.source--; | ||
return container; | ||
}; | ||
GLTFUtil.getImageSize = function (container, index) { | ||
var image = container.json.images[index]; | ||
var isPNG; | ||
} | ||
static getImageSize(container, index) { | ||
const image = container.json.images[index]; | ||
let isPNG; | ||
if (image.mimeType) { | ||
@@ -564,7 +557,7 @@ isPNG = image.mimeType === 'image/png'; | ||
} | ||
var arrayBuffer = container.resolveURI(image.uri); | ||
const arrayBuffer = container.resolveURI(image.uri); | ||
return isPNG | ||
? getSizePNG(Buffer.from(arrayBuffer)) | ||
: getSizeJPEG(Buffer.from(arrayBuffer)); | ||
}; | ||
} | ||
/** | ||
@@ -575,4 +568,4 @@ * Removes a texture from the glTF container. | ||
*/ | ||
GLTFUtil.removeTexture = function (container, index) { | ||
container.json.materials.forEach(function (material) { | ||
static removeTexture(container, index) { | ||
container.json.materials.forEach((material) => { | ||
[ | ||
@@ -584,3 +577,3 @@ material.emissiveTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.metallicRoughnessTexture | ||
].forEach(function (texture) { | ||
].forEach((texture) => { | ||
if (texture.index === index) { | ||
@@ -596,3 +589,3 @@ throw new Error('Texture still in use.'); | ||
return container; | ||
}; | ||
} | ||
/** | ||
@@ -604,9 +597,9 @@ * Adds a new buffer to the glTF container. | ||
*/ | ||
GLTFUtil.addBuffer = function (container, name, arrayBuffer) { | ||
var uri = name + ".bin"; | ||
var buffer = { name: name, uri: uri, byteLength: arrayBuffer.byteLength }; | ||
static addBuffer(container, name, arrayBuffer) { | ||
const uri = `${name}.bin`; | ||
const buffer = { name, uri, byteLength: arrayBuffer.byteLength }; | ||
container.json.buffers.push(buffer); | ||
container.resources[uri] = arrayBuffer; | ||
return buffer; | ||
}; | ||
} | ||
/** | ||
@@ -617,11 +610,11 @@ * Removes a buffer from the glTF container. Fails if buffer is still in use. | ||
*/ | ||
GLTFUtil.removeBuffer = function (container, index) { | ||
var bufferViews = container.json.bufferViews.filter(function (view) { return view.buffer === index; }); | ||
static removeBuffer(container, index) { | ||
const bufferViews = container.json.bufferViews.filter((view) => view.buffer === index); | ||
if (bufferViews.length) { | ||
throw new Error("Buffer is in use by " + bufferViews.length + " bufferViews and cannot be removed."); | ||
throw new Error(`Buffer is in use by ${bufferViews.length} bufferViews and cannot be removed.`); | ||
} | ||
var buffer = container.json.buffers[index]; | ||
const buffer = container.json.buffers[index]; | ||
container.json.buffers.splice(index, 1); | ||
delete container.resources[buffer.uri]; | ||
container.json.bufferViews.forEach(function (bufferView) { | ||
container.json.bufferViews.forEach((bufferView) => { | ||
if (bufferView.buffer >= index) | ||
@@ -631,31 +624,30 @@ bufferView.buffer--; | ||
return buffer; | ||
}; | ||
GLTFUtil.addBufferView = function (container, arrayBuffer, bufferIndex) { | ||
if (bufferIndex === void 0) { bufferIndex = 0; } | ||
var buffer = container.json.buffers[bufferIndex]; | ||
var resource = container.getBuffer(bufferIndex); | ||
var byteOffset = resource.byteLength; | ||
} | ||
static addBufferView(container, arrayBuffer, bufferIndex = 0) { | ||
const buffer = container.json.buffers[bufferIndex]; | ||
let resource = container.getBuffer(bufferIndex); | ||
const byteOffset = resource.byteLength; | ||
resource = GLTFUtil.join(resource, arrayBuffer); | ||
container.setBuffer(bufferIndex, resource); | ||
buffer.byteLength = resource.byteLength; | ||
var bufferView = { buffer: bufferIndex, byteLength: arrayBuffer.byteLength, byteOffset: byteOffset }; | ||
const bufferView = { buffer: bufferIndex, byteLength: arrayBuffer.byteLength, byteOffset }; | ||
container.json.bufferViews.push(bufferView); | ||
return bufferView; | ||
}; | ||
} | ||
/** Removes bufferView, after checking to see whether it is used by any accessors. */ | ||
GLTFUtil.removeBufferView = function (container, bufferViewIndex) { | ||
var bufferView = container.json.bufferViews[bufferViewIndex]; | ||
var accessors = container.json.accessors.filter(function (accessor) { return accessor.bufferView === bufferViewIndex; }); | ||
static removeBufferView(container, bufferViewIndex) { | ||
const bufferView = container.json.bufferViews[bufferViewIndex]; | ||
const accessors = container.json.accessors.filter((accessor) => accessor.bufferView === bufferViewIndex); | ||
if (accessors.length) { | ||
throw new Error("Buffer is in use by " + accessors.length + " accessors and cannot be removed."); | ||
throw new Error(`Buffer is in use by ${accessors.length} accessors and cannot be removed.`); | ||
} | ||
if (bufferView.byteLength > 0) { | ||
var resource = container.getBuffer(bufferView.buffer); | ||
resource = this.splice(resource, bufferView.byteOffset, bufferView.byteLength)[0]; | ||
let resource = container.getBuffer(bufferView.buffer); | ||
[resource] = this.splice(resource, bufferView.byteOffset, bufferView.byteLength); | ||
container.setBuffer(bufferView.buffer, resource); | ||
var buffer = container.json.buffers[bufferView.buffer]; | ||
const buffer = container.json.buffers[bufferView.buffer]; | ||
buffer.byteLength -= bufferView.byteLength; | ||
container.json.bufferViews.forEach(function (bufferView) { | ||
if (bufferView.byteOffset > bufferView.byteOffset) { | ||
bufferView.byteOffset -= bufferView.byteLength; | ||
container.json.bufferViews.forEach((otherBufferView) => { | ||
if (otherBufferView.buffer === bufferView.buffer && otherBufferView.byteOffset > bufferView.byteOffset) { | ||
otherBufferView.byteOffset -= bufferView.byteLength; | ||
} | ||
@@ -665,3 +657,3 @@ }); | ||
container.json.bufferViews.splice(bufferViewIndex, 1); | ||
container.json.accessors.forEach(function (accessor) { | ||
container.json.accessors.forEach((accessor) => { | ||
if (accessor.bufferView > bufferViewIndex) | ||
@@ -671,16 +663,16 @@ accessor.bufferView--; | ||
return bufferView; | ||
}; | ||
GLTFUtil.addAccessor = function (container, array, type, componentType, count, target) { | ||
var bufferView = this.addBufferView(container, array.buffer, 0); | ||
} | ||
static addAccessor(container, array, type, componentType, count, target) { | ||
const bufferView = this.addBufferView(container, array.buffer, 0); | ||
bufferView['target'] = target; // TODO: Add to typings. | ||
var accessor = { | ||
const accessor = { | ||
bufferView: container.json.bufferViews.length - 1, | ||
byteOffset: 0, | ||
type: type, | ||
componentType: componentType, | ||
count: count | ||
type, | ||
componentType, | ||
count | ||
}; | ||
container.json.accessors.push(accessor); | ||
return accessor; | ||
}; | ||
} | ||
/** | ||
@@ -691,9 +683,9 @@ * Removes accessor, without checking to see whether it is used. | ||
*/ | ||
GLTFUtil.removeAccessor = function (container, index) { | ||
static removeAccessor(container, index) { | ||
if ((container.json.animations || []).length > 0) { | ||
throw new Error('Not implemented: cannot remove accessors from animated models.'); | ||
} | ||
var accessor = container.json.accessors[index]; | ||
var byteOffset = accessor.byteOffset || 0; | ||
var byteLength = GLTFUtil.getAccessorByteLength(accessor); | ||
const accessor = container.json.accessors[index]; | ||
const byteOffset = accessor.byteOffset || 0; | ||
const byteLength = GLTFUtil.getAccessorByteLength(accessor); | ||
if (byteLength) { | ||
@@ -705,3 +697,3 @@ this.spliceBufferView(container, accessor.bufferView, byteOffset, byteLength); | ||
// update byteOffset of other accessors | ||
container.json.accessors.forEach(function (otherAccessor) { | ||
container.json.accessors.forEach((otherAccessor) => { | ||
if (otherAccessor.bufferView === accessor.bufferView && (otherAccessor.byteOffset || 0) > byteOffset) { | ||
@@ -712,5 +704,5 @@ otherAccessor.byteOffset -= byteLength; | ||
// update pointers into following accessors | ||
container.json.meshes.forEach(function (mesh) { | ||
mesh.primitives.forEach(function (primitive) { | ||
for (var semantic in primitive.attributes) { | ||
container.json.meshes.forEach((mesh) => { | ||
mesh.primitives.forEach((primitive) => { | ||
for (let semantic in primitive.attributes) { | ||
if (primitive.attributes[semantic] === index) { | ||
@@ -732,3 +724,3 @@ throw new Error('Unexpected accessor use.'); | ||
return accessor; | ||
}; | ||
} | ||
/** | ||
@@ -740,12 +732,11 @@ * Removes data from a bufferView, updating other affected bufferviews. | ||
*/ | ||
GLTFUtil.spliceBufferView = function (container, bufferViewIndex, byteOffset, byteLength) { | ||
var _a; | ||
var bufferView = container.json.bufferViews[bufferViewIndex]; | ||
var bufferData = container.getBuffer(bufferView.buffer); | ||
var splicedData; | ||
_a = GLTFUtil.splice(bufferData, (bufferView.byteOffset || 0) + byteOffset, byteLength), bufferData = _a[0], splicedData = _a[1]; | ||
static spliceBufferView(container, bufferViewIndex, byteOffset, byteLength) { | ||
const bufferView = container.json.bufferViews[bufferViewIndex]; | ||
let bufferData = container.getBuffer(bufferView.buffer); | ||
let splicedData; | ||
[bufferData, splicedData] = GLTFUtil.splice(bufferData, (bufferView.byteOffset || 0) + byteOffset, byteLength); | ||
container.setBuffer(bufferView.buffer, bufferData); | ||
container.json.buffers[bufferView.buffer].byteLength -= byteLength; // TODO: do this when setBuffer is called? | ||
bufferView.byteLength -= byteLength; | ||
container.json.bufferViews.forEach(function (otherBufferView) { | ||
container.json.bufferViews.forEach((otherBufferView) => { | ||
if (bufferView.buffer === otherBufferView.buffer && (bufferView.byteOffset || 0) < (otherBufferView.byteOffset || 0)) { | ||
@@ -756,25 +747,25 @@ otherBufferView.byteOffset -= byteLength; | ||
return splicedData; | ||
}; | ||
GLTFUtil.getAccessorByteLength = function (accessor) { | ||
var itemSize = AccessorTypeData[accessor.type].size; | ||
var valueSize = AccessorComponentTypeData[accessor.componentType].size; | ||
} | ||
static getAccessorByteLength(accessor) { | ||
const itemSize = AccessorTypeData[accessor.type].size; | ||
const valueSize = AccessorComponentTypeData[accessor.componentType].size; | ||
return itemSize * valueSize * accessor.count; | ||
}; | ||
} | ||
/** | ||
* Removes segment from an arraybuffer, returning two arraybuffers: [original, removed]. | ||
*/ | ||
GLTFUtil.splice = function (buffer, begin, count) { | ||
var a1 = buffer.slice(0, begin); | ||
var a2 = buffer.slice(begin + count); | ||
var a = this.join(a1, a2); | ||
var b = buffer.slice(begin, begin + count); | ||
static splice(buffer, begin, count) { | ||
const a1 = buffer.slice(0, begin); | ||
const a2 = buffer.slice(begin + count); | ||
const a = this.join(a1, a2); | ||
const b = buffer.slice(begin, begin + count); | ||
return [a, b]; | ||
}; | ||
} | ||
/** Joins two ArrayBuffers. */ | ||
GLTFUtil.join = function (a, b) { | ||
var out = new Uint8Array(a.byteLength + b.byteLength); | ||
static join(a, b) { | ||
const out = new Uint8Array(a.byteLength + b.byteLength); | ||
out.set(new Uint8Array(a), 0); | ||
out.set(new Uint8Array(b), a.byteLength); | ||
return out.buffer; | ||
}; | ||
} | ||
/** | ||
@@ -784,3 +775,3 @@ * Pad buffer to the next 4-byte boundary. | ||
*/ | ||
GLTFUtil.pad = function (arrayBuffer, paddingByte) { | ||
static pad(arrayBuffer, paddingByte) { | ||
paddingByte = paddingByte || 0; | ||
@@ -799,4 +790,4 @@ var paddedLength = Math.ceil(arrayBuffer.byteLength / 4) * 4; | ||
return arrayBuffer; | ||
}; | ||
GLTFUtil.arrayBufferEquals = function (a, b) { | ||
} | ||
static arrayBufferEquals(a, b) { | ||
if (a === b) | ||
@@ -806,5 +797,5 @@ return true; | ||
return false; | ||
var view1 = new DataView(a); | ||
var view2 = new DataView(b); | ||
var i = a.byteLength; | ||
const view1 = new DataView(a); | ||
const view2 = new DataView(b); | ||
let i = a.byteLength; | ||
while (i--) { | ||
@@ -815,31 +806,29 @@ if (view1.getUint8(i) !== view2.getUint8(i)) | ||
return true; | ||
}; | ||
return GLTFUtil; | ||
}()); | ||
} | ||
} | ||
var NodeIO = /** @class */ (function () { | ||
function NodeIO(fs, path) { | ||
class NodeIO { | ||
constructor(fs, path) { | ||
this.fs = fs; | ||
this.path = path; | ||
} | ||
NodeIO.prototype.read = function (uri) { | ||
var isGLB = !!uri.match(/\.glb$/); | ||
read(uri) { | ||
const isGLB = !!uri.match(/\.glb$/); | ||
return isGLB ? this.readGLB(uri) : this.readGLTF(uri); | ||
}; | ||
NodeIO.prototype.readGLB = function (uri) { | ||
var buffer = this.fs.readFileSync(uri); | ||
var arrayBuffer = GLTFUtil.trimBuffer(buffer); | ||
} | ||
readGLB(uri) { | ||
const buffer = this.fs.readFileSync(uri); | ||
const arrayBuffer = GLTFUtil.trimBuffer(buffer); | ||
return GLTFUtil.fromGLB(arrayBuffer); | ||
}; | ||
NodeIO.prototype.readGLTF = function (uri) { | ||
var _this = this; | ||
var dir = this.path.dirname(uri); | ||
var json = JSON.parse(this.fs.readFileSync(uri, 'utf8')); | ||
var resources = {}; | ||
var images = json.images || []; | ||
var buffers = json.buffers || []; | ||
images.concat(buffers).forEach(function (resource) { | ||
} | ||
readGLTF(uri) { | ||
const dir = this.path.dirname(uri); | ||
const json = JSON.parse(this.fs.readFileSync(uri, 'utf8')); | ||
const resources = {}; | ||
const images = json.images || []; | ||
const buffers = json.buffers || []; | ||
[...images, ...buffers].forEach((resource) => { | ||
if (resource.uri && !resource.uri.match(/data:/)) { | ||
var absURI = _this.path.resolve(dir, resource.uri); | ||
resources[resource.uri] = GLTFUtil.trimBuffer(_this.fs.readFileSync(absURI)); | ||
const absURI = this.path.resolve(dir, resource.uri); | ||
resources[resource.uri] = GLTFUtil.trimBuffer(this.fs.readFileSync(absURI)); | ||
} | ||
@@ -851,46 +840,45 @@ else { | ||
return GLTFUtil.fromGLTF(json, resources); | ||
}; | ||
NodeIO.prototype.write = function (uri, container) { | ||
var isGLB = !!uri.match(/\.glb$/); | ||
} | ||
write(uri, container) { | ||
const isGLB = !!uri.match(/\.glb$/); | ||
isGLB ? this.writeGLB(uri, container) : this.writeGLTF(uri, container); | ||
}; | ||
NodeIO.prototype.writeGLTF = function (uri, container, embedded) { | ||
} | ||
writeGLTF(uri, container, embedded) { | ||
if (embedded) { | ||
throw new Error('Not implemented.'); | ||
} | ||
var _a = this, fs = _a.fs, path = _a.path; | ||
var dir = path.dirname(uri); | ||
var json = container.json, resources = container.resources; | ||
const { fs, path } = this; | ||
const dir = path.dirname(uri); | ||
const { json, resources } = container; | ||
fs.writeFileSync(uri, JSON.stringify(json)); | ||
Object.keys(resources).forEach(function (resourceName) { | ||
var resource = new Buffer(resources[resourceName]); | ||
Object.keys(resources).forEach((resourceName) => { | ||
const resource = new Buffer(resources[resourceName]); | ||
fs.writeFileSync(path.join(dir, resourceName), resource); | ||
}); | ||
}; | ||
NodeIO.prototype.writeGLB = function (uri, container) { | ||
var glbBuffer = GLTFUtil.toGLB(container); | ||
var buffer = Buffer.from(glbBuffer); | ||
} | ||
writeGLB(uri, container) { | ||
const glbBuffer = GLTFUtil.toGLB(container); | ||
const buffer = Buffer.from(glbBuffer); | ||
this.fs.writeFileSync(uri, buffer); | ||
}; | ||
return NodeIO; | ||
}()); | ||
var WebIO = /** @class */ (function () { | ||
function WebIO(fetchConfig) { | ||
} | ||
} | ||
class WebIO { | ||
constructor(fetchConfig) { | ||
this.fetchConfig = fetchConfig; | ||
} | ||
WebIO.prototype.read = function (uri) { | ||
var isGLB = !!uri.match(/\.glb$/); | ||
read(uri) { | ||
const isGLB = !!uri.match(/\.glb$/); | ||
return isGLB ? this.readGLB(uri) : this.readGLTF(uri); | ||
}; | ||
WebIO.prototype.readGLTF = function (uri) { | ||
var _this = this; | ||
} | ||
readGLTF(uri) { | ||
return fetch(uri, this.fetchConfig) | ||
.then(function (response) { return response.json(); }) | ||
.then(function (json) { | ||
var resources = {}; | ||
var pendingResources = json.images.concat(json.buffers).map(function (resource) { | ||
.then((response) => response.json()) | ||
.then((json) => { | ||
const resources = {}; | ||
const pendingResources = [...json.images, ...json.buffers] | ||
.map((resource) => { | ||
if (resource.uri) { | ||
return fetch(resource.uri, _this.fetchConfig) | ||
.then(function (response) { return response.arrayBuffer(); }) | ||
.then(function (arrayBuffer) { | ||
return fetch(resource.uri, this.fetchConfig) | ||
.then((response) => response.arrayBuffer()) | ||
.then((arrayBuffer) => { | ||
resources[resource.uri] = arrayBuffer; | ||
@@ -904,12 +892,11 @@ }); | ||
return Promise.all(pendingResources) | ||
.then(function () { return GLTFUtil.fromGLTF(json, resources); }); | ||
.then(() => GLTFUtil.fromGLTF(json, resources)); | ||
}); | ||
}; | ||
WebIO.prototype.readGLB = function (uri) { | ||
} | ||
readGLB(uri) { | ||
return fetch(uri, this.fetchConfig) | ||
.then(function (response) { return response.arrayBuffer(); }) | ||
.then(function (arrayBuffer) { return GLTFUtil.fromGLB(arrayBuffer); }); | ||
}; | ||
return WebIO; | ||
}()); | ||
.then((response) => response.arrayBuffer()) | ||
.then((arrayBuffer) => GLTFUtil.fromGLB(arrayBuffer)); | ||
} | ||
} | ||
@@ -916,0 +903,0 @@ exports.GLTFUtil = GLTFUtil; |
@@ -1,2 +0,2 @@ | ||
var AccessorType = { | ||
const AccessorType = { | ||
SCALAR: 'SCALAR', | ||
@@ -10,3 +10,3 @@ VEC2: 'VEC2', | ||
}; | ||
var AccessorTypeData = { | ||
const AccessorTypeData = { | ||
SCALAR: { value: 'SCALAR', size: 1 }, | ||
@@ -20,3 +20,3 @@ VEC2: { value: 'VEC2', size: 2 }, | ||
}; | ||
var AccessorComponentType = { | ||
const AccessorComponentType = { | ||
BYTE: 5120, | ||
@@ -29,3 +29,3 @@ UNSIGNED_BYTE: 5121, | ||
}; | ||
var AccessorComponentTypeData = { | ||
const AccessorComponentTypeData = { | ||
'5120': { value: 'BYTE', size: 1 }, | ||
@@ -38,3 +38,3 @@ '5121': { value: 'UNSIGNED_BYTE', size: 1 }, | ||
}; | ||
var BufferViewTarget = { | ||
const BufferViewTarget = { | ||
ARRAY_BUFFER: 34962, | ||
@@ -47,4 +47,4 @@ ELEMENT_ARRAY_BUFFER: 34963 | ||
*/ | ||
var GLTFContainer = /** @class */ (function () { | ||
function GLTFContainer(json, resources) { | ||
class GLTFContainer { | ||
constructor(json, resources) { | ||
this.json = json; | ||
@@ -57,41 +57,41 @@ this.resources = resources; | ||
*/ | ||
GLTFContainer.prototype.resolveURI = function (uri) { | ||
resolveURI(uri) { | ||
return this.resources[uri]; | ||
}; | ||
GLTFContainer.prototype.getBuffer = function (bufferIndex) { | ||
} | ||
getBuffer(bufferIndex) { | ||
return this.resolveURI(this.json.buffers[bufferIndex].uri); | ||
}; | ||
GLTFContainer.prototype.setBuffer = function (bufferIndex, buffer) { | ||
} | ||
setBuffer(bufferIndex, buffer) { | ||
this.resources[this.json.buffers[bufferIndex].uri] = buffer; | ||
}; | ||
} | ||
/** | ||
* Creates a deep copy of the asset. | ||
*/ | ||
GLTFContainer.prototype.clone = function () { | ||
var json = JSON.parse(JSON.stringify(this.json)); | ||
var resources = {}; | ||
for (var uri in this.resources) { | ||
var resource = this.resolveURI(uri); | ||
clone() { | ||
const json = JSON.parse(JSON.stringify(this.json)); | ||
const resources = {}; | ||
for (const uri in this.resources) { | ||
const resource = this.resolveURI(uri); | ||
resources[uri] = resource.slice(0); | ||
} | ||
return new GLTFContainer(json, resources); | ||
}; | ||
GLTFContainer.prototype.validate = function () { | ||
} | ||
validate() { | ||
if (this.json.buffers.length > 1) { | ||
throw new Error("Expected one buffer, found " + this.json.buffers.length + "."); | ||
throw new Error(`Expected one buffer, found ${this.json.buffers.length}.`); | ||
} | ||
var embeddedImages = (this.json.images || []).filter(function (image) { return image.bufferView !== undefined; }); | ||
const embeddedImages = (this.json.images || []).filter((image) => image.bufferView !== undefined); | ||
if (embeddedImages.length) { | ||
throw new Error("Expected only external images, found " + embeddedImages.length + " embedded."); | ||
throw new Error(`Expected only external images, found ${embeddedImages.length} embedded.`); | ||
} | ||
var embeddedBuffers = this.json.buffers.filter(function (buffer) { return buffer.uri === undefined; }); | ||
const embeddedBuffers = this.json.buffers.filter((buffer) => buffer.uri === undefined); | ||
if (embeddedBuffers.length) { | ||
throw new Error("Expected exactly one buffer, which should be external, and found " + embeddedBuffers.length + " embedded."); | ||
throw new Error(`Expected exactly one buffer, which should be external, and found ${embeddedBuffers.length} embedded.`); | ||
} | ||
for (var key in this.json) { | ||
if (Array.isArray(this.json[key]) && this.json[key].length === 0) { | ||
throw new Error("Empty top-level array, \"" + this.json[key] + "\"."); | ||
throw new Error(`Empty top-level array, "${this.json[key]}".`); | ||
} | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -101,9 +101,9 @@ * Returns the accessor for the given index, as a typed array. | ||
*/ | ||
GLTFContainer.prototype.getAccessorArray = function (index) { | ||
var accessor = this.json.accessors[index]; | ||
var bufferView = this.json.bufferViews[accessor.bufferView]; | ||
var buffer = this.json.buffers[bufferView.buffer]; | ||
var resource = this.resources[buffer.uri]; | ||
var valueSize = AccessorTypeData[accessor.type].size; | ||
var start = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0); | ||
getAccessorArray(index) { | ||
const accessor = this.json.accessors[index]; | ||
const bufferView = this.json.bufferViews[accessor.bufferView]; | ||
const buffer = this.json.buffers[bufferView.buffer]; | ||
const resource = this.resources[buffer.uri]; | ||
const valueSize = AccessorTypeData[accessor.type].size; | ||
const start = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0); | ||
switch (accessor.componentType) { | ||
@@ -119,6 +119,6 @@ case AccessorComponentType.FLOAT: | ||
default: | ||
throw new Error("Accessor componentType " + accessor.componentType + " not implemented."); | ||
throw new Error(`Accessor componentType ${accessor.componentType} not implemented.`); | ||
} | ||
}; | ||
GLTFContainer.prototype.equals = function (other) { | ||
} | ||
equals(other) { | ||
if (JSON.stringify(this.json) !== JSON.stringify(other.json)) | ||
@@ -128,5 +128,5 @@ return false; | ||
return false; | ||
for (var resourceName in this.resources) { | ||
var resource = Buffer.from(this.resources[resourceName]); | ||
var otherResource = Buffer.from(other.resources[resourceName]); | ||
for (const resourceName in this.resources) { | ||
const resource = Buffer.from(this.resources[resourceName]); | ||
const otherResource = Buffer.from(other.resources[resourceName]); | ||
if (!resource.equals(otherResource)) | ||
@@ -136,5 +136,4 @@ return false; | ||
return true; | ||
}; | ||
return GLTFContainer; | ||
}()); | ||
} | ||
} | ||
@@ -151,4 +150,4 @@ var LoggerVerbosity; | ||
*/ | ||
var Logger = /** @class */ (function () { | ||
function Logger(name, verbosity) { | ||
class Logger { | ||
constructor(name, verbosity) { | ||
this.name = name; | ||
@@ -161,7 +160,7 @@ this.verbosity = verbosity; | ||
*/ | ||
Logger.prototype.info = function (text) { | ||
info(text) { | ||
if (this.verbosity <= LoggerVerbosity.INFO) { | ||
console.log(this.name + ": " + text); | ||
console.log(`${this.name}: ${text}`); | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -171,7 +170,7 @@ * Logs at level WARNING. | ||
*/ | ||
Logger.prototype.warn = function (text) { | ||
warn(text) { | ||
if (this.verbosity <= LoggerVerbosity.WARNING) { | ||
console.warn(this.name + ": " + text); | ||
console.warn(`${this.name}: ${text}`); | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -181,16 +180,15 @@ * Logs at level ERROR. | ||
*/ | ||
Logger.prototype.error = function (text) { | ||
error(text) { | ||
if (this.verbosity <= LoggerVerbosity.ERROR) { | ||
console.error(this.name + ": " + text); | ||
console.error(`${this.name}: ${text}`); | ||
} | ||
}; | ||
return Logger; | ||
}()); | ||
} | ||
} | ||
var PackedGLTFContainer = /** @class */ (function () { | ||
function PackedGLTFContainer(json, buffer) { | ||
class PackedGLTFContainer { | ||
constructor(json, buffer) { | ||
this.json = json; | ||
this.buffer = buffer; | ||
} | ||
PackedGLTFContainer.prototype.getBuffer = function (bufferIndex) { | ||
getBuffer(bufferIndex) { | ||
if (bufferIndex !== 0) { | ||
@@ -200,4 +198,4 @@ throw new Error('Invalid buffer index.'); | ||
return this.buffer; | ||
}; | ||
PackedGLTFContainer.prototype.setBuffer = function (bufferIndex, buffer) { | ||
} | ||
setBuffer(bufferIndex, buffer) { | ||
if (bufferIndex !== 0) { | ||
@@ -207,9 +205,9 @@ throw new Error('Invalid buffer index.'); | ||
this.buffer = buffer; | ||
}; | ||
PackedGLTFContainer.prototype.validate = function () { | ||
} | ||
validate() { | ||
if (this.json.buffers.length > 1) { | ||
throw new Error("Expected 1 buffer, found " + this.json.buffers.length + "."); | ||
throw new Error(`Expected 1 buffer, found ${this.json.buffers.length}.`); | ||
} | ||
var externalImages = (this.json.images || []).filter(function (image) { return image.uri !== undefined; }); | ||
var externalBuffers = this.json.buffers.filter(function (buffer) { return buffer.uri !== undefined; }); | ||
const externalImages = (this.json.images || []).filter((image) => image.uri !== undefined); | ||
const externalBuffers = this.json.buffers.filter((buffer) => buffer.uri !== undefined); | ||
if (externalImages.length || externalBuffers.length) { | ||
@@ -220,15 +218,15 @@ throw new Error('Found external resource references.'); | ||
if (Array.isArray(this.json[key]) && this.json[key].length === 0) { | ||
throw new Error("Empty top-level array, \"" + this.json[key] + "\"."); | ||
throw new Error(`Empty top-level array, "${this.json[key]}".`); | ||
} | ||
} | ||
}; | ||
PackedGLTFContainer.pack = function (container) { | ||
} | ||
static pack(container) { | ||
container.validate(); | ||
container = container.clone(); | ||
var json = container.json; | ||
var buffer = container.resolveURI(container.json.buffers[0].uri); | ||
const json = container.json; | ||
const buffer = container.resolveURI(container.json.buffers[0].uri); | ||
delete json.buffers[0].uri; | ||
var packedContainer = new PackedGLTFContainer(json, buffer); | ||
(json.images || []).forEach(function (image) { | ||
var imageData = container.resolveURI(image.uri); | ||
const packedContainer = new PackedGLTFContainer(json, buffer); | ||
(json.images || []).forEach((image) => { | ||
const imageData = container.resolveURI(image.uri); | ||
delete image.uri; | ||
@@ -240,18 +238,17 @@ GLTFUtil.addBufferView(packedContainer, imageData, 0); | ||
return packedContainer; | ||
}; | ||
PackedGLTFContainer.prototype.unpack = function () { | ||
var _this = this; | ||
var json = JSON.parse(JSON.stringify(this.json)); | ||
var buffer = this.buffer.slice(0); | ||
var resources = { 'resources.bin': buffer }; | ||
} | ||
unpack() { | ||
const json = JSON.parse(JSON.stringify(this.json)); | ||
let buffer = this.buffer.slice(0); | ||
const resources = { 'resources.bin': buffer }; | ||
json.buffers[0].uri = 'resources.bin'; | ||
var container = new GLTFContainer(json, resources); | ||
(json.images || []).forEach(function (image, imageIndex) { | ||
var bufferViewIndex = image.bufferView; | ||
var bufferView = json.bufferViews[bufferViewIndex]; | ||
const container = new GLTFContainer(json, resources); | ||
(json.images || []).forEach((image, imageIndex) => { | ||
const bufferViewIndex = image.bufferView; | ||
const bufferView = json.bufferViews[bufferViewIndex]; | ||
delete image.bufferView; | ||
var imageData = _this.buffer.slice(bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength); | ||
GLTFUtil.removeBufferView(_this, bufferViewIndex); | ||
var extension = image.mimeType === 'image/jpeg' ? 'jpg' : 'png'; | ||
image.uri = image.name ? image.name.replace(/\.\w+$/, '') + ("." + extension) : "image-" + imageIndex + "." + extension; | ||
const imageData = this.buffer.slice(bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength); | ||
GLTFUtil.removeBufferView(this, bufferViewIndex); | ||
const extension = image.mimeType === 'image/jpeg' ? 'jpg' : 'png'; | ||
image.uri = image.name ? image.name.replace(/\.\w+$/, '') + `.${extension}` : `image-${imageIndex}.${extension}`; | ||
resources[image.uri] = imageData; | ||
@@ -261,5 +258,4 @@ }); | ||
return container; | ||
}; | ||
return PackedGLTFContainer; | ||
}()); | ||
} | ||
} | ||
@@ -322,5 +318,3 @@ //////////////////////////////////////////////////////// | ||
*/ | ||
var GLTFUtil = /** @class */ (function () { | ||
function GLTFUtil() { | ||
} | ||
class GLTFUtil { | ||
/** | ||
@@ -331,5 +325,5 @@ * Creates a GLTFContainer from the given JSON and files. | ||
*/ | ||
GLTFUtil.fromGLTF = function (json, resources) { | ||
static fromGLTF(json, resources) { | ||
return new GLTFContainer(json, resources); | ||
}; | ||
} | ||
/** | ||
@@ -339,5 +333,5 @@ * Creates a GLTFContainer from the given GLB binary. | ||
*/ | ||
GLTFUtil.fromGLB = function (glb) { | ||
static fromGLB(glb) { | ||
// Decode and verify GLB header. | ||
var header = new Uint32Array(glb, 0, 3); | ||
const header = new Uint32Array(glb, 0, 3); | ||
if (header[0] !== 0x46546C67) { | ||
@@ -347,9 +341,9 @@ throw new Error('Invalid glTF asset.'); | ||
else if (header[1] !== 2) { | ||
throw new Error("Unsupported glTF binary version, \"" + header[1] + "\"."); | ||
throw new Error(`Unsupported glTF binary version, "${header[1]}".`); | ||
} | ||
// Decode and verify chunk headers. | ||
var jsonChunkHeader = new Uint32Array(glb, 12, 2); | ||
var jsonByteOffset = 20; | ||
var jsonByteLength = jsonChunkHeader[0]; | ||
var binaryChunkHeader = new Uint32Array(glb, jsonByteOffset + jsonByteLength, 2); | ||
const jsonChunkHeader = new Uint32Array(glb, 12, 2); | ||
const jsonByteOffset = 20; | ||
const jsonByteLength = jsonChunkHeader[0]; | ||
const binaryChunkHeader = new Uint32Array(glb, jsonByteOffset + jsonByteLength, 2); | ||
if (jsonChunkHeader[1] !== 0x4E4F534A || binaryChunkHeader[1] !== 0x004E4942) { | ||
@@ -359,9 +353,9 @@ throw new Error('Unexpected GLB layout.'); | ||
// Decode content. | ||
var jsonText = this.decodeText(glb.slice(jsonByteOffset, jsonByteOffset + jsonByteLength)); | ||
var json = JSON.parse(jsonText); | ||
var binaryByteOffset = jsonByteOffset + jsonByteLength + 8; | ||
var binaryByteLength = binaryChunkHeader[0]; | ||
var binary = glb.slice(binaryByteOffset, binaryByteOffset + binaryByteLength); | ||
const jsonText = this.decodeText(glb.slice(jsonByteOffset, jsonByteOffset + jsonByteLength)); | ||
const json = JSON.parse(jsonText); | ||
const binaryByteOffset = jsonByteOffset + jsonByteLength + 8; | ||
const binaryByteLength = binaryChunkHeader[0]; | ||
const binary = glb.slice(binaryByteOffset, binaryByteOffset + binaryByteLength); | ||
return new PackedGLTFContainer(json, binary).unpack(); | ||
}; | ||
} | ||
/** | ||
@@ -371,6 +365,6 @@ * Serializes a GLTFContainer to GLTF JSON and external files. | ||
*/ | ||
GLTFUtil.toGLTF = function (container) { | ||
var json = container.json, resources = container.resources; | ||
return { json: json, resources: resources }; | ||
}; | ||
static toGLTF(container) { | ||
const { json, resources } = container; | ||
return { json, resources }; | ||
} | ||
/** | ||
@@ -380,16 +374,16 @@ * Serializes a GLTFContainer to a GLB binary. | ||
*/ | ||
GLTFUtil.toGLB = function (container) { | ||
static toGLB(container) { | ||
if (container instanceof GLTFContainer) { | ||
container = PackedGLTFContainer.pack(container); | ||
} | ||
var jsonText = JSON.stringify(container.json); | ||
var jsonChunkData = this.pad(GLTFUtil.encodeText(jsonText), 0x20); | ||
var jsonChunkHeader = new Uint32Array([jsonChunkData.byteLength, 0x4E4F534A]).buffer; | ||
var jsonChunk = this.join(jsonChunkHeader, jsonChunkData); | ||
var binaryChunkData = this.pad(container.getBuffer(0), 0x00); | ||
var binaryChunkHeader = new Uint32Array([binaryChunkData.byteLength, 0x004E4942]).buffer; | ||
var binaryChunk = this.join(binaryChunkHeader, binaryChunkData); | ||
var header = new Uint32Array([0x46546C67, 2, 12 + jsonChunk.byteLength + binaryChunk.byteLength]).buffer; | ||
const jsonText = JSON.stringify(container.json); | ||
const jsonChunkData = this.pad(GLTFUtil.encodeText(jsonText), 0x20); | ||
const jsonChunkHeader = new Uint32Array([jsonChunkData.byteLength, 0x4E4F534A]).buffer; | ||
const jsonChunk = this.join(jsonChunkHeader, jsonChunkData); | ||
const binaryChunkData = this.pad(container.getBuffer(0), 0x00); | ||
const binaryChunkHeader = new Uint32Array([binaryChunkData.byteLength, 0x004E4942]).buffer; | ||
const binaryChunk = this.join(binaryChunkHeader, binaryChunkData); | ||
const header = new Uint32Array([0x46546C67, 2, 12 + jsonChunk.byteLength + binaryChunk.byteLength]).buffer; | ||
return this.join(this.join(header, jsonChunk), binaryChunk); | ||
}; | ||
} | ||
/** | ||
@@ -399,8 +393,8 @@ * Creates a buffer from a Data URI. | ||
*/ | ||
GLTFUtil.createBufferFromDataURI = function (dataURI) { | ||
static createBufferFromDataURI(dataURI) { | ||
if (typeof Buffer === 'undefined') { | ||
// Browser. | ||
var byteString = atob(dataURI.split(',')[1]); | ||
var ia = new Uint8Array(byteString.length); | ||
for (var i = 0; i < byteString.length; i++) { | ||
const byteString = atob(dataURI.split(',')[1]); | ||
const ia = new Uint8Array(byteString.length); | ||
for (let i = 0; i < byteString.length; i++) { | ||
ia[i] = byteString.charCodeAt(i); | ||
@@ -414,7 +408,7 @@ } | ||
} | ||
}; | ||
GLTFUtil.createLogger = function (name, verbosity) { | ||
} | ||
static createLogger(name, verbosity) { | ||
return new Logger(name, verbosity); | ||
}; | ||
GLTFUtil.encodeText = function (text) { | ||
} | ||
static encodeText(text) { | ||
if (typeof TextEncoder !== 'undefined') { | ||
@@ -424,17 +418,16 @@ return new TextEncoder().encode(text).buffer; | ||
return this.trimBuffer(Buffer.from(text)); | ||
}; | ||
GLTFUtil.decodeText = function (buffer) { | ||
} | ||
static decodeText(buffer) { | ||
if (typeof TextDecoder !== 'undefined') { | ||
return new TextDecoder().decode(buffer); | ||
} | ||
var a = Buffer.from(buffer); | ||
const a = Buffer.from(buffer); | ||
return a.toString('utf8'); | ||
}; | ||
GLTFUtil.trimBuffer = function (buffer) { | ||
var byteOffset = buffer.byteOffset, byteLength = buffer.byteLength; | ||
} | ||
static trimBuffer(buffer) { | ||
const { byteOffset, byteLength } = buffer; | ||
return buffer.buffer.slice(byteOffset, byteOffset + byteLength); | ||
}; | ||
GLTFUtil.analyze = function (container) { | ||
var _this = this; | ||
var report = { | ||
} | ||
static analyze(container) { | ||
const report = { | ||
meshes: (container.json.meshes || []).length, | ||
@@ -455,16 +448,16 @@ textures: (container.json.textures || []).length, | ||
// Primitives and targets. | ||
(container.json.meshes || []).forEach(function (mesh) { | ||
(container.json.meshes || []).forEach((mesh) => { | ||
report.primitives += mesh.primitives.length; | ||
mesh.primitives.forEach(function (primitive) { | ||
mesh.primitives.forEach((primitive) => { | ||
if (primitive.indices !== undefined) { | ||
report.dataUsage.geometry += _this.getAccessorByteLength(container.json.accessors[primitive.indices]); | ||
report.dataUsage.geometry += this.getAccessorByteLength(container.json.accessors[primitive.indices]); | ||
} | ||
Object.keys(primitive.attributes).forEach(function (attr) { | ||
var accessor = container.json.accessors[primitive.attributes[attr]]; | ||
report.dataUsage.geometry += _this.getAccessorByteLength(accessor); | ||
Object.keys(primitive.attributes).forEach((attr) => { | ||
const accessor = container.json.accessors[primitive.attributes[attr]]; | ||
report.dataUsage.geometry += this.getAccessorByteLength(accessor); | ||
}); | ||
(primitive.targets || []).forEach(function (target) { | ||
Object.keys(target).forEach(function (attr) { | ||
var accessor = container.json.accessors[target[attr]]; | ||
report.dataUsage.targets += _this.getAccessorByteLength(accessor); | ||
(primitive.targets || []).forEach((target) => { | ||
Object.keys(target).forEach((attr) => { | ||
const accessor = container.json.accessors[target[attr]]; | ||
report.dataUsage.targets += this.getAccessorByteLength(accessor); | ||
}); | ||
@@ -475,12 +468,12 @@ }); | ||
// Animation | ||
(container.json.animations || []).forEach(function (animation) { | ||
animation.samplers.forEach(function (sampler) { | ||
var input = container.json.accessors[sampler.input]; | ||
var output = container.json.accessors[sampler.output]; | ||
report.dataUsage.animation += _this.getAccessorByteLength(input); | ||
report.dataUsage.animation += _this.getAccessorByteLength(output); | ||
(container.json.animations || []).forEach((animation) => { | ||
animation.samplers.forEach((sampler) => { | ||
const input = container.json.accessors[sampler.input]; | ||
const output = container.json.accessors[sampler.output]; | ||
report.dataUsage.animation += this.getAccessorByteLength(input); | ||
report.dataUsage.animation += this.getAccessorByteLength(output); | ||
}); | ||
}); | ||
// Textures | ||
(container.json.images || []).forEach(function (image) { | ||
(container.json.images || []).forEach((image) => { | ||
if (image.uri !== undefined) { | ||
@@ -496,3 +489,3 @@ report.dataUsage.textures += container.resolveURI(image.uri).byteLength; | ||
return report; | ||
}; | ||
} | ||
/** | ||
@@ -505,21 +498,21 @@ * Adds a new image to the glTF container. | ||
*/ | ||
GLTFUtil.addImage = function (container, name, file, type) { | ||
var uri, mimeType; | ||
static addImage(container, name, file, type) { | ||
let uri, mimeType; | ||
switch (type) { | ||
case 'image/jpeg': | ||
uri = name + ".jpg"; | ||
uri = `${name}.jpg`; | ||
mimeType = 'image/jpeg'; | ||
break; | ||
case 'image/png': | ||
uri = name + ".png"; | ||
uri = `${name}.png`; | ||
mimeType = 'image/png'; | ||
break; | ||
default: | ||
throw new Error("Unsupported image type, \"" + type + "\"."); | ||
throw new Error(`Unsupported image type, "${type}".`); | ||
} | ||
container.json.images = container.json.images || []; | ||
container.json.images.push({ name: name, mimeType: mimeType, uri: uri }); | ||
container.json.images.push({ name, mimeType, uri }); | ||
container.resources[uri] = file; | ||
return container; | ||
}; | ||
} | ||
/** | ||
@@ -530,9 +523,9 @@ * Removes an image from the glTF container. Fails if image is still in use. | ||
*/ | ||
GLTFUtil.removeImage = function (container, index) { | ||
var textures = container.json.textures.filter(function (texture) { return texture.source === index; }); | ||
static removeImage(container, index) { | ||
const textures = container.json.textures.filter((texture) => texture.source === index); | ||
if (textures.length) { | ||
throw new Error("Image is in use by " + textures.length + " textures and cannot be removed."); | ||
throw new Error(`Image is in use by ${textures.length} textures and cannot be removed.`); | ||
} | ||
var image = container.json.images[index]; | ||
var imageBuffer = container.resolveURI(image.uri); | ||
const image = container.json.images[index]; | ||
const imageBuffer = container.resolveURI(image.uri); | ||
if (!imageBuffer) { | ||
@@ -542,3 +535,3 @@ throw new Error('No such image, or image is embedded.'); | ||
container.json.images.splice(index, 1); | ||
container.json.textures.forEach(function (texture) { | ||
container.json.textures.forEach((texture) => { | ||
if (texture.source > index) | ||
@@ -549,6 +542,6 @@ texture.source--; | ||
return container; | ||
}; | ||
GLTFUtil.getImageSize = function (container, index) { | ||
var image = container.json.images[index]; | ||
var isPNG; | ||
} | ||
static getImageSize(container, index) { | ||
const image = container.json.images[index]; | ||
let isPNG; | ||
if (image.mimeType) { | ||
@@ -560,7 +553,7 @@ isPNG = image.mimeType === 'image/png'; | ||
} | ||
var arrayBuffer = container.resolveURI(image.uri); | ||
const arrayBuffer = container.resolveURI(image.uri); | ||
return isPNG | ||
? getSizePNG(Buffer.from(arrayBuffer)) | ||
: getSizeJPEG(Buffer.from(arrayBuffer)); | ||
}; | ||
} | ||
/** | ||
@@ -571,4 +564,4 @@ * Removes a texture from the glTF container. | ||
*/ | ||
GLTFUtil.removeTexture = function (container, index) { | ||
container.json.materials.forEach(function (material) { | ||
static removeTexture(container, index) { | ||
container.json.materials.forEach((material) => { | ||
[ | ||
@@ -580,3 +573,3 @@ material.emissiveTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.metallicRoughnessTexture | ||
].forEach(function (texture) { | ||
].forEach((texture) => { | ||
if (texture.index === index) { | ||
@@ -592,3 +585,3 @@ throw new Error('Texture still in use.'); | ||
return container; | ||
}; | ||
} | ||
/** | ||
@@ -600,9 +593,9 @@ * Adds a new buffer to the glTF container. | ||
*/ | ||
GLTFUtil.addBuffer = function (container, name, arrayBuffer) { | ||
var uri = name + ".bin"; | ||
var buffer = { name: name, uri: uri, byteLength: arrayBuffer.byteLength }; | ||
static addBuffer(container, name, arrayBuffer) { | ||
const uri = `${name}.bin`; | ||
const buffer = { name, uri, byteLength: arrayBuffer.byteLength }; | ||
container.json.buffers.push(buffer); | ||
container.resources[uri] = arrayBuffer; | ||
return buffer; | ||
}; | ||
} | ||
/** | ||
@@ -613,11 +606,11 @@ * Removes a buffer from the glTF container. Fails if buffer is still in use. | ||
*/ | ||
GLTFUtil.removeBuffer = function (container, index) { | ||
var bufferViews = container.json.bufferViews.filter(function (view) { return view.buffer === index; }); | ||
static removeBuffer(container, index) { | ||
const bufferViews = container.json.bufferViews.filter((view) => view.buffer === index); | ||
if (bufferViews.length) { | ||
throw new Error("Buffer is in use by " + bufferViews.length + " bufferViews and cannot be removed."); | ||
throw new Error(`Buffer is in use by ${bufferViews.length} bufferViews and cannot be removed.`); | ||
} | ||
var buffer = container.json.buffers[index]; | ||
const buffer = container.json.buffers[index]; | ||
container.json.buffers.splice(index, 1); | ||
delete container.resources[buffer.uri]; | ||
container.json.bufferViews.forEach(function (bufferView) { | ||
container.json.bufferViews.forEach((bufferView) => { | ||
if (bufferView.buffer >= index) | ||
@@ -627,31 +620,30 @@ bufferView.buffer--; | ||
return buffer; | ||
}; | ||
GLTFUtil.addBufferView = function (container, arrayBuffer, bufferIndex) { | ||
if (bufferIndex === void 0) { bufferIndex = 0; } | ||
var buffer = container.json.buffers[bufferIndex]; | ||
var resource = container.getBuffer(bufferIndex); | ||
var byteOffset = resource.byteLength; | ||
} | ||
static addBufferView(container, arrayBuffer, bufferIndex = 0) { | ||
const buffer = container.json.buffers[bufferIndex]; | ||
let resource = container.getBuffer(bufferIndex); | ||
const byteOffset = resource.byteLength; | ||
resource = GLTFUtil.join(resource, arrayBuffer); | ||
container.setBuffer(bufferIndex, resource); | ||
buffer.byteLength = resource.byteLength; | ||
var bufferView = { buffer: bufferIndex, byteLength: arrayBuffer.byteLength, byteOffset: byteOffset }; | ||
const bufferView = { buffer: bufferIndex, byteLength: arrayBuffer.byteLength, byteOffset }; | ||
container.json.bufferViews.push(bufferView); | ||
return bufferView; | ||
}; | ||
} | ||
/** Removes bufferView, after checking to see whether it is used by any accessors. */ | ||
GLTFUtil.removeBufferView = function (container, bufferViewIndex) { | ||
var bufferView = container.json.bufferViews[bufferViewIndex]; | ||
var accessors = container.json.accessors.filter(function (accessor) { return accessor.bufferView === bufferViewIndex; }); | ||
static removeBufferView(container, bufferViewIndex) { | ||
const bufferView = container.json.bufferViews[bufferViewIndex]; | ||
const accessors = container.json.accessors.filter((accessor) => accessor.bufferView === bufferViewIndex); | ||
if (accessors.length) { | ||
throw new Error("Buffer is in use by " + accessors.length + " accessors and cannot be removed."); | ||
throw new Error(`Buffer is in use by ${accessors.length} accessors and cannot be removed.`); | ||
} | ||
if (bufferView.byteLength > 0) { | ||
var resource = container.getBuffer(bufferView.buffer); | ||
resource = this.splice(resource, bufferView.byteOffset, bufferView.byteLength)[0]; | ||
let resource = container.getBuffer(bufferView.buffer); | ||
[resource] = this.splice(resource, bufferView.byteOffset, bufferView.byteLength); | ||
container.setBuffer(bufferView.buffer, resource); | ||
var buffer = container.json.buffers[bufferView.buffer]; | ||
const buffer = container.json.buffers[bufferView.buffer]; | ||
buffer.byteLength -= bufferView.byteLength; | ||
container.json.bufferViews.forEach(function (bufferView) { | ||
if (bufferView.byteOffset > bufferView.byteOffset) { | ||
bufferView.byteOffset -= bufferView.byteLength; | ||
container.json.bufferViews.forEach((otherBufferView) => { | ||
if (otherBufferView.buffer === bufferView.buffer && otherBufferView.byteOffset > bufferView.byteOffset) { | ||
otherBufferView.byteOffset -= bufferView.byteLength; | ||
} | ||
@@ -661,3 +653,3 @@ }); | ||
container.json.bufferViews.splice(bufferViewIndex, 1); | ||
container.json.accessors.forEach(function (accessor) { | ||
container.json.accessors.forEach((accessor) => { | ||
if (accessor.bufferView > bufferViewIndex) | ||
@@ -667,16 +659,16 @@ accessor.bufferView--; | ||
return bufferView; | ||
}; | ||
GLTFUtil.addAccessor = function (container, array, type, componentType, count, target) { | ||
var bufferView = this.addBufferView(container, array.buffer, 0); | ||
} | ||
static addAccessor(container, array, type, componentType, count, target) { | ||
const bufferView = this.addBufferView(container, array.buffer, 0); | ||
bufferView['target'] = target; // TODO: Add to typings. | ||
var accessor = { | ||
const accessor = { | ||
bufferView: container.json.bufferViews.length - 1, | ||
byteOffset: 0, | ||
type: type, | ||
componentType: componentType, | ||
count: count | ||
type, | ||
componentType, | ||
count | ||
}; | ||
container.json.accessors.push(accessor); | ||
return accessor; | ||
}; | ||
} | ||
/** | ||
@@ -687,9 +679,9 @@ * Removes accessor, without checking to see whether it is used. | ||
*/ | ||
GLTFUtil.removeAccessor = function (container, index) { | ||
static removeAccessor(container, index) { | ||
if ((container.json.animations || []).length > 0) { | ||
throw new Error('Not implemented: cannot remove accessors from animated models.'); | ||
} | ||
var accessor = container.json.accessors[index]; | ||
var byteOffset = accessor.byteOffset || 0; | ||
var byteLength = GLTFUtil.getAccessorByteLength(accessor); | ||
const accessor = container.json.accessors[index]; | ||
const byteOffset = accessor.byteOffset || 0; | ||
const byteLength = GLTFUtil.getAccessorByteLength(accessor); | ||
if (byteLength) { | ||
@@ -701,3 +693,3 @@ this.spliceBufferView(container, accessor.bufferView, byteOffset, byteLength); | ||
// update byteOffset of other accessors | ||
container.json.accessors.forEach(function (otherAccessor) { | ||
container.json.accessors.forEach((otherAccessor) => { | ||
if (otherAccessor.bufferView === accessor.bufferView && (otherAccessor.byteOffset || 0) > byteOffset) { | ||
@@ -708,5 +700,5 @@ otherAccessor.byteOffset -= byteLength; | ||
// update pointers into following accessors | ||
container.json.meshes.forEach(function (mesh) { | ||
mesh.primitives.forEach(function (primitive) { | ||
for (var semantic in primitive.attributes) { | ||
container.json.meshes.forEach((mesh) => { | ||
mesh.primitives.forEach((primitive) => { | ||
for (let semantic in primitive.attributes) { | ||
if (primitive.attributes[semantic] === index) { | ||
@@ -728,3 +720,3 @@ throw new Error('Unexpected accessor use.'); | ||
return accessor; | ||
}; | ||
} | ||
/** | ||
@@ -736,12 +728,11 @@ * Removes data from a bufferView, updating other affected bufferviews. | ||
*/ | ||
GLTFUtil.spliceBufferView = function (container, bufferViewIndex, byteOffset, byteLength) { | ||
var _a; | ||
var bufferView = container.json.bufferViews[bufferViewIndex]; | ||
var bufferData = container.getBuffer(bufferView.buffer); | ||
var splicedData; | ||
_a = GLTFUtil.splice(bufferData, (bufferView.byteOffset || 0) + byteOffset, byteLength), bufferData = _a[0], splicedData = _a[1]; | ||
static spliceBufferView(container, bufferViewIndex, byteOffset, byteLength) { | ||
const bufferView = container.json.bufferViews[bufferViewIndex]; | ||
let bufferData = container.getBuffer(bufferView.buffer); | ||
let splicedData; | ||
[bufferData, splicedData] = GLTFUtil.splice(bufferData, (bufferView.byteOffset || 0) + byteOffset, byteLength); | ||
container.setBuffer(bufferView.buffer, bufferData); | ||
container.json.buffers[bufferView.buffer].byteLength -= byteLength; // TODO: do this when setBuffer is called? | ||
bufferView.byteLength -= byteLength; | ||
container.json.bufferViews.forEach(function (otherBufferView) { | ||
container.json.bufferViews.forEach((otherBufferView) => { | ||
if (bufferView.buffer === otherBufferView.buffer && (bufferView.byteOffset || 0) < (otherBufferView.byteOffset || 0)) { | ||
@@ -752,25 +743,25 @@ otherBufferView.byteOffset -= byteLength; | ||
return splicedData; | ||
}; | ||
GLTFUtil.getAccessorByteLength = function (accessor) { | ||
var itemSize = AccessorTypeData[accessor.type].size; | ||
var valueSize = AccessorComponentTypeData[accessor.componentType].size; | ||
} | ||
static getAccessorByteLength(accessor) { | ||
const itemSize = AccessorTypeData[accessor.type].size; | ||
const valueSize = AccessorComponentTypeData[accessor.componentType].size; | ||
return itemSize * valueSize * accessor.count; | ||
}; | ||
} | ||
/** | ||
* Removes segment from an arraybuffer, returning two arraybuffers: [original, removed]. | ||
*/ | ||
GLTFUtil.splice = function (buffer, begin, count) { | ||
var a1 = buffer.slice(0, begin); | ||
var a2 = buffer.slice(begin + count); | ||
var a = this.join(a1, a2); | ||
var b = buffer.slice(begin, begin + count); | ||
static splice(buffer, begin, count) { | ||
const a1 = buffer.slice(0, begin); | ||
const a2 = buffer.slice(begin + count); | ||
const a = this.join(a1, a2); | ||
const b = buffer.slice(begin, begin + count); | ||
return [a, b]; | ||
}; | ||
} | ||
/** Joins two ArrayBuffers. */ | ||
GLTFUtil.join = function (a, b) { | ||
var out = new Uint8Array(a.byteLength + b.byteLength); | ||
static join(a, b) { | ||
const out = new Uint8Array(a.byteLength + b.byteLength); | ||
out.set(new Uint8Array(a), 0); | ||
out.set(new Uint8Array(b), a.byteLength); | ||
return out.buffer; | ||
}; | ||
} | ||
/** | ||
@@ -780,3 +771,3 @@ * Pad buffer to the next 4-byte boundary. | ||
*/ | ||
GLTFUtil.pad = function (arrayBuffer, paddingByte) { | ||
static pad(arrayBuffer, paddingByte) { | ||
paddingByte = paddingByte || 0; | ||
@@ -795,4 +786,4 @@ var paddedLength = Math.ceil(arrayBuffer.byteLength / 4) * 4; | ||
return arrayBuffer; | ||
}; | ||
GLTFUtil.arrayBufferEquals = function (a, b) { | ||
} | ||
static arrayBufferEquals(a, b) { | ||
if (a === b) | ||
@@ -802,5 +793,5 @@ return true; | ||
return false; | ||
var view1 = new DataView(a); | ||
var view2 = new DataView(b); | ||
var i = a.byteLength; | ||
const view1 = new DataView(a); | ||
const view2 = new DataView(b); | ||
let i = a.byteLength; | ||
while (i--) { | ||
@@ -811,31 +802,29 @@ if (view1.getUint8(i) !== view2.getUint8(i)) | ||
return true; | ||
}; | ||
return GLTFUtil; | ||
}()); | ||
} | ||
} | ||
var NodeIO = /** @class */ (function () { | ||
function NodeIO(fs, path) { | ||
class NodeIO { | ||
constructor(fs, path) { | ||
this.fs = fs; | ||
this.path = path; | ||
} | ||
NodeIO.prototype.read = function (uri) { | ||
var isGLB = !!uri.match(/\.glb$/); | ||
read(uri) { | ||
const isGLB = !!uri.match(/\.glb$/); | ||
return isGLB ? this.readGLB(uri) : this.readGLTF(uri); | ||
}; | ||
NodeIO.prototype.readGLB = function (uri) { | ||
var buffer = this.fs.readFileSync(uri); | ||
var arrayBuffer = GLTFUtil.trimBuffer(buffer); | ||
} | ||
readGLB(uri) { | ||
const buffer = this.fs.readFileSync(uri); | ||
const arrayBuffer = GLTFUtil.trimBuffer(buffer); | ||
return GLTFUtil.fromGLB(arrayBuffer); | ||
}; | ||
NodeIO.prototype.readGLTF = function (uri) { | ||
var _this = this; | ||
var dir = this.path.dirname(uri); | ||
var json = JSON.parse(this.fs.readFileSync(uri, 'utf8')); | ||
var resources = {}; | ||
var images = json.images || []; | ||
var buffers = json.buffers || []; | ||
images.concat(buffers).forEach(function (resource) { | ||
} | ||
readGLTF(uri) { | ||
const dir = this.path.dirname(uri); | ||
const json = JSON.parse(this.fs.readFileSync(uri, 'utf8')); | ||
const resources = {}; | ||
const images = json.images || []; | ||
const buffers = json.buffers || []; | ||
[...images, ...buffers].forEach((resource) => { | ||
if (resource.uri && !resource.uri.match(/data:/)) { | ||
var absURI = _this.path.resolve(dir, resource.uri); | ||
resources[resource.uri] = GLTFUtil.trimBuffer(_this.fs.readFileSync(absURI)); | ||
const absURI = this.path.resolve(dir, resource.uri); | ||
resources[resource.uri] = GLTFUtil.trimBuffer(this.fs.readFileSync(absURI)); | ||
} | ||
@@ -847,46 +836,45 @@ else { | ||
return GLTFUtil.fromGLTF(json, resources); | ||
}; | ||
NodeIO.prototype.write = function (uri, container) { | ||
var isGLB = !!uri.match(/\.glb$/); | ||
} | ||
write(uri, container) { | ||
const isGLB = !!uri.match(/\.glb$/); | ||
isGLB ? this.writeGLB(uri, container) : this.writeGLTF(uri, container); | ||
}; | ||
NodeIO.prototype.writeGLTF = function (uri, container, embedded) { | ||
} | ||
writeGLTF(uri, container, embedded) { | ||
if (embedded) { | ||
throw new Error('Not implemented.'); | ||
} | ||
var _a = this, fs = _a.fs, path = _a.path; | ||
var dir = path.dirname(uri); | ||
var json = container.json, resources = container.resources; | ||
const { fs, path } = this; | ||
const dir = path.dirname(uri); | ||
const { json, resources } = container; | ||
fs.writeFileSync(uri, JSON.stringify(json)); | ||
Object.keys(resources).forEach(function (resourceName) { | ||
var resource = new Buffer(resources[resourceName]); | ||
Object.keys(resources).forEach((resourceName) => { | ||
const resource = new Buffer(resources[resourceName]); | ||
fs.writeFileSync(path.join(dir, resourceName), resource); | ||
}); | ||
}; | ||
NodeIO.prototype.writeGLB = function (uri, container) { | ||
var glbBuffer = GLTFUtil.toGLB(container); | ||
var buffer = Buffer.from(glbBuffer); | ||
} | ||
writeGLB(uri, container) { | ||
const glbBuffer = GLTFUtil.toGLB(container); | ||
const buffer = Buffer.from(glbBuffer); | ||
this.fs.writeFileSync(uri, buffer); | ||
}; | ||
return NodeIO; | ||
}()); | ||
var WebIO = /** @class */ (function () { | ||
function WebIO(fetchConfig) { | ||
} | ||
} | ||
class WebIO { | ||
constructor(fetchConfig) { | ||
this.fetchConfig = fetchConfig; | ||
} | ||
WebIO.prototype.read = function (uri) { | ||
var isGLB = !!uri.match(/\.glb$/); | ||
read(uri) { | ||
const isGLB = !!uri.match(/\.glb$/); | ||
return isGLB ? this.readGLB(uri) : this.readGLTF(uri); | ||
}; | ||
WebIO.prototype.readGLTF = function (uri) { | ||
var _this = this; | ||
} | ||
readGLTF(uri) { | ||
return fetch(uri, this.fetchConfig) | ||
.then(function (response) { return response.json(); }) | ||
.then(function (json) { | ||
var resources = {}; | ||
var pendingResources = json.images.concat(json.buffers).map(function (resource) { | ||
.then((response) => response.json()) | ||
.then((json) => { | ||
const resources = {}; | ||
const pendingResources = [...json.images, ...json.buffers] | ||
.map((resource) => { | ||
if (resource.uri) { | ||
return fetch(resource.uri, _this.fetchConfig) | ||
.then(function (response) { return response.arrayBuffer(); }) | ||
.then(function (arrayBuffer) { | ||
return fetch(resource.uri, this.fetchConfig) | ||
.then((response) => response.arrayBuffer()) | ||
.then((arrayBuffer) => { | ||
resources[resource.uri] = arrayBuffer; | ||
@@ -900,13 +888,12 @@ }); | ||
return Promise.all(pendingResources) | ||
.then(function () { return GLTFUtil.fromGLTF(json, resources); }); | ||
.then(() => GLTFUtil.fromGLTF(json, resources)); | ||
}); | ||
}; | ||
WebIO.prototype.readGLB = function (uri) { | ||
} | ||
readGLB(uri) { | ||
return fetch(uri, this.fetchConfig) | ||
.then(function (response) { return response.arrayBuffer(); }) | ||
.then(function (arrayBuffer) { return GLTFUtil.fromGLB(arrayBuffer); }); | ||
}; | ||
return WebIO; | ||
}()); | ||
.then((response) => response.arrayBuffer()) | ||
.then((arrayBuffer) => GLTFUtil.fromGLB(arrayBuffer)); | ||
} | ||
} | ||
export { GLTFUtil, GLTFContainer, NodeIO, WebIO, Logger, LoggerVerbosity, AccessorType, AccessorTypeData, AccessorComponentType, AccessorComponentTypeData, BufferViewTarget }; |
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
factory(global.gltfTransform = global.gltfTransform || {}, global.gltfTransform.core = {}); | ||
}(typeof self !== 'undefined' ? self : this, function (exports) { 'use strict'; | ||
(global = global || self, factory((global.gltfTransform = global.gltfTransform || {}, global.gltfTransform.core = {}))); | ||
}(this, function (exports) { 'use strict'; | ||
var AccessorType = { | ||
const AccessorType = { | ||
SCALAR: 'SCALAR', | ||
@@ -16,3 +16,3 @@ VEC2: 'VEC2', | ||
}; | ||
var AccessorTypeData = { | ||
const AccessorTypeData = { | ||
SCALAR: { value: 'SCALAR', size: 1 }, | ||
@@ -26,3 +26,3 @@ VEC2: { value: 'VEC2', size: 2 }, | ||
}; | ||
var AccessorComponentType = { | ||
const AccessorComponentType = { | ||
BYTE: 5120, | ||
@@ -35,3 +35,3 @@ UNSIGNED_BYTE: 5121, | ||
}; | ||
var AccessorComponentTypeData = { | ||
const AccessorComponentTypeData = { | ||
'5120': { value: 'BYTE', size: 1 }, | ||
@@ -44,3 +44,3 @@ '5121': { value: 'UNSIGNED_BYTE', size: 1 }, | ||
}; | ||
var BufferViewTarget = { | ||
const BufferViewTarget = { | ||
ARRAY_BUFFER: 34962, | ||
@@ -53,4 +53,4 @@ ELEMENT_ARRAY_BUFFER: 34963 | ||
*/ | ||
var GLTFContainer = /** @class */ (function () { | ||
function GLTFContainer(json, resources) { | ||
class GLTFContainer { | ||
constructor(json, resources) { | ||
this.json = json; | ||
@@ -63,41 +63,41 @@ this.resources = resources; | ||
*/ | ||
GLTFContainer.prototype.resolveURI = function (uri) { | ||
resolveURI(uri) { | ||
return this.resources[uri]; | ||
}; | ||
GLTFContainer.prototype.getBuffer = function (bufferIndex) { | ||
} | ||
getBuffer(bufferIndex) { | ||
return this.resolveURI(this.json.buffers[bufferIndex].uri); | ||
}; | ||
GLTFContainer.prototype.setBuffer = function (bufferIndex, buffer) { | ||
} | ||
setBuffer(bufferIndex, buffer) { | ||
this.resources[this.json.buffers[bufferIndex].uri] = buffer; | ||
}; | ||
} | ||
/** | ||
* Creates a deep copy of the asset. | ||
*/ | ||
GLTFContainer.prototype.clone = function () { | ||
var json = JSON.parse(JSON.stringify(this.json)); | ||
var resources = {}; | ||
for (var uri in this.resources) { | ||
var resource = this.resolveURI(uri); | ||
clone() { | ||
const json = JSON.parse(JSON.stringify(this.json)); | ||
const resources = {}; | ||
for (const uri in this.resources) { | ||
const resource = this.resolveURI(uri); | ||
resources[uri] = resource.slice(0); | ||
} | ||
return new GLTFContainer(json, resources); | ||
}; | ||
GLTFContainer.prototype.validate = function () { | ||
} | ||
validate() { | ||
if (this.json.buffers.length > 1) { | ||
throw new Error("Expected one buffer, found " + this.json.buffers.length + "."); | ||
throw new Error(`Expected one buffer, found ${this.json.buffers.length}.`); | ||
} | ||
var embeddedImages = (this.json.images || []).filter(function (image) { return image.bufferView !== undefined; }); | ||
const embeddedImages = (this.json.images || []).filter((image) => image.bufferView !== undefined); | ||
if (embeddedImages.length) { | ||
throw new Error("Expected only external images, found " + embeddedImages.length + " embedded."); | ||
throw new Error(`Expected only external images, found ${embeddedImages.length} embedded.`); | ||
} | ||
var embeddedBuffers = this.json.buffers.filter(function (buffer) { return buffer.uri === undefined; }); | ||
const embeddedBuffers = this.json.buffers.filter((buffer) => buffer.uri === undefined); | ||
if (embeddedBuffers.length) { | ||
throw new Error("Expected exactly one buffer, which should be external, and found " + embeddedBuffers.length + " embedded."); | ||
throw new Error(`Expected exactly one buffer, which should be external, and found ${embeddedBuffers.length} embedded.`); | ||
} | ||
for (var key in this.json) { | ||
if (Array.isArray(this.json[key]) && this.json[key].length === 0) { | ||
throw new Error("Empty top-level array, \"" + this.json[key] + "\"."); | ||
throw new Error(`Empty top-level array, "${this.json[key]}".`); | ||
} | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -107,9 +107,9 @@ * Returns the accessor for the given index, as a typed array. | ||
*/ | ||
GLTFContainer.prototype.getAccessorArray = function (index) { | ||
var accessor = this.json.accessors[index]; | ||
var bufferView = this.json.bufferViews[accessor.bufferView]; | ||
var buffer = this.json.buffers[bufferView.buffer]; | ||
var resource = this.resources[buffer.uri]; | ||
var valueSize = AccessorTypeData[accessor.type].size; | ||
var start = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0); | ||
getAccessorArray(index) { | ||
const accessor = this.json.accessors[index]; | ||
const bufferView = this.json.bufferViews[accessor.bufferView]; | ||
const buffer = this.json.buffers[bufferView.buffer]; | ||
const resource = this.resources[buffer.uri]; | ||
const valueSize = AccessorTypeData[accessor.type].size; | ||
const start = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0); | ||
switch (accessor.componentType) { | ||
@@ -125,6 +125,6 @@ case AccessorComponentType.FLOAT: | ||
default: | ||
throw new Error("Accessor componentType " + accessor.componentType + " not implemented."); | ||
throw new Error(`Accessor componentType ${accessor.componentType} not implemented.`); | ||
} | ||
}; | ||
GLTFContainer.prototype.equals = function (other) { | ||
} | ||
equals(other) { | ||
if (JSON.stringify(this.json) !== JSON.stringify(other.json)) | ||
@@ -134,5 +134,5 @@ return false; | ||
return false; | ||
for (var resourceName in this.resources) { | ||
var resource = Buffer.from(this.resources[resourceName]); | ||
var otherResource = Buffer.from(other.resources[resourceName]); | ||
for (const resourceName in this.resources) { | ||
const resource = Buffer.from(this.resources[resourceName]); | ||
const otherResource = Buffer.from(other.resources[resourceName]); | ||
if (!resource.equals(otherResource)) | ||
@@ -142,5 +142,4 @@ return false; | ||
return true; | ||
}; | ||
return GLTFContainer; | ||
}()); | ||
} | ||
} | ||
@@ -156,4 +155,4 @@ (function (LoggerVerbosity) { | ||
*/ | ||
var Logger = /** @class */ (function () { | ||
function Logger(name, verbosity) { | ||
class Logger { | ||
constructor(name, verbosity) { | ||
this.name = name; | ||
@@ -166,7 +165,7 @@ this.verbosity = verbosity; | ||
*/ | ||
Logger.prototype.info = function (text) { | ||
info(text) { | ||
if (this.verbosity <= exports.LoggerVerbosity.INFO) { | ||
console.log(this.name + ": " + text); | ||
console.log(`${this.name}: ${text}`); | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -176,7 +175,7 @@ * Logs at level WARNING. | ||
*/ | ||
Logger.prototype.warn = function (text) { | ||
warn(text) { | ||
if (this.verbosity <= exports.LoggerVerbosity.WARNING) { | ||
console.warn(this.name + ": " + text); | ||
console.warn(`${this.name}: ${text}`); | ||
} | ||
}; | ||
} | ||
/** | ||
@@ -186,16 +185,15 @@ * Logs at level ERROR. | ||
*/ | ||
Logger.prototype.error = function (text) { | ||
error(text) { | ||
if (this.verbosity <= exports.LoggerVerbosity.ERROR) { | ||
console.error(this.name + ": " + text); | ||
console.error(`${this.name}: ${text}`); | ||
} | ||
}; | ||
return Logger; | ||
}()); | ||
} | ||
} | ||
var PackedGLTFContainer = /** @class */ (function () { | ||
function PackedGLTFContainer(json, buffer) { | ||
class PackedGLTFContainer { | ||
constructor(json, buffer) { | ||
this.json = json; | ||
this.buffer = buffer; | ||
} | ||
PackedGLTFContainer.prototype.getBuffer = function (bufferIndex) { | ||
getBuffer(bufferIndex) { | ||
if (bufferIndex !== 0) { | ||
@@ -205,4 +203,4 @@ throw new Error('Invalid buffer index.'); | ||
return this.buffer; | ||
}; | ||
PackedGLTFContainer.prototype.setBuffer = function (bufferIndex, buffer) { | ||
} | ||
setBuffer(bufferIndex, buffer) { | ||
if (bufferIndex !== 0) { | ||
@@ -212,9 +210,9 @@ throw new Error('Invalid buffer index.'); | ||
this.buffer = buffer; | ||
}; | ||
PackedGLTFContainer.prototype.validate = function () { | ||
} | ||
validate() { | ||
if (this.json.buffers.length > 1) { | ||
throw new Error("Expected 1 buffer, found " + this.json.buffers.length + "."); | ||
throw new Error(`Expected 1 buffer, found ${this.json.buffers.length}.`); | ||
} | ||
var externalImages = (this.json.images || []).filter(function (image) { return image.uri !== undefined; }); | ||
var externalBuffers = this.json.buffers.filter(function (buffer) { return buffer.uri !== undefined; }); | ||
const externalImages = (this.json.images || []).filter((image) => image.uri !== undefined); | ||
const externalBuffers = this.json.buffers.filter((buffer) => buffer.uri !== undefined); | ||
if (externalImages.length || externalBuffers.length) { | ||
@@ -225,15 +223,15 @@ throw new Error('Found external resource references.'); | ||
if (Array.isArray(this.json[key]) && this.json[key].length === 0) { | ||
throw new Error("Empty top-level array, \"" + this.json[key] + "\"."); | ||
throw new Error(`Empty top-level array, "${this.json[key]}".`); | ||
} | ||
} | ||
}; | ||
PackedGLTFContainer.pack = function (container) { | ||
} | ||
static pack(container) { | ||
container.validate(); | ||
container = container.clone(); | ||
var json = container.json; | ||
var buffer = container.resolveURI(container.json.buffers[0].uri); | ||
const json = container.json; | ||
const buffer = container.resolveURI(container.json.buffers[0].uri); | ||
delete json.buffers[0].uri; | ||
var packedContainer = new PackedGLTFContainer(json, buffer); | ||
(json.images || []).forEach(function (image) { | ||
var imageData = container.resolveURI(image.uri); | ||
const packedContainer = new PackedGLTFContainer(json, buffer); | ||
(json.images || []).forEach((image) => { | ||
const imageData = container.resolveURI(image.uri); | ||
delete image.uri; | ||
@@ -245,18 +243,17 @@ GLTFUtil.addBufferView(packedContainer, imageData, 0); | ||
return packedContainer; | ||
}; | ||
PackedGLTFContainer.prototype.unpack = function () { | ||
var _this = this; | ||
var json = JSON.parse(JSON.stringify(this.json)); | ||
var buffer = this.buffer.slice(0); | ||
var resources = { 'resources.bin': buffer }; | ||
} | ||
unpack() { | ||
const json = JSON.parse(JSON.stringify(this.json)); | ||
let buffer = this.buffer.slice(0); | ||
const resources = { 'resources.bin': buffer }; | ||
json.buffers[0].uri = 'resources.bin'; | ||
var container = new GLTFContainer(json, resources); | ||
(json.images || []).forEach(function (image, imageIndex) { | ||
var bufferViewIndex = image.bufferView; | ||
var bufferView = json.bufferViews[bufferViewIndex]; | ||
const container = new GLTFContainer(json, resources); | ||
(json.images || []).forEach((image, imageIndex) => { | ||
const bufferViewIndex = image.bufferView; | ||
const bufferView = json.bufferViews[bufferViewIndex]; | ||
delete image.bufferView; | ||
var imageData = _this.buffer.slice(bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength); | ||
GLTFUtil.removeBufferView(_this, bufferViewIndex); | ||
var extension = image.mimeType === 'image/jpeg' ? 'jpg' : 'png'; | ||
image.uri = image.name ? image.name.replace(/\.\w+$/, '') + ("." + extension) : "image-" + imageIndex + "." + extension; | ||
const imageData = this.buffer.slice(bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength); | ||
GLTFUtil.removeBufferView(this, bufferViewIndex); | ||
const extension = image.mimeType === 'image/jpeg' ? 'jpg' : 'png'; | ||
image.uri = image.name ? image.name.replace(/\.\w+$/, '') + `.${extension}` : `image-${imageIndex}.${extension}`; | ||
resources[image.uri] = imageData; | ||
@@ -266,5 +263,4 @@ }); | ||
return container; | ||
}; | ||
return PackedGLTFContainer; | ||
}()); | ||
} | ||
} | ||
@@ -327,5 +323,3 @@ //////////////////////////////////////////////////////// | ||
*/ | ||
var GLTFUtil = /** @class */ (function () { | ||
function GLTFUtil() { | ||
} | ||
class GLTFUtil { | ||
/** | ||
@@ -336,5 +330,5 @@ * Creates a GLTFContainer from the given JSON and files. | ||
*/ | ||
GLTFUtil.fromGLTF = function (json, resources) { | ||
static fromGLTF(json, resources) { | ||
return new GLTFContainer(json, resources); | ||
}; | ||
} | ||
/** | ||
@@ -344,5 +338,5 @@ * Creates a GLTFContainer from the given GLB binary. | ||
*/ | ||
GLTFUtil.fromGLB = function (glb) { | ||
static fromGLB(glb) { | ||
// Decode and verify GLB header. | ||
var header = new Uint32Array(glb, 0, 3); | ||
const header = new Uint32Array(glb, 0, 3); | ||
if (header[0] !== 0x46546C67) { | ||
@@ -352,9 +346,9 @@ throw new Error('Invalid glTF asset.'); | ||
else if (header[1] !== 2) { | ||
throw new Error("Unsupported glTF binary version, \"" + header[1] + "\"."); | ||
throw new Error(`Unsupported glTF binary version, "${header[1]}".`); | ||
} | ||
// Decode and verify chunk headers. | ||
var jsonChunkHeader = new Uint32Array(glb, 12, 2); | ||
var jsonByteOffset = 20; | ||
var jsonByteLength = jsonChunkHeader[0]; | ||
var binaryChunkHeader = new Uint32Array(glb, jsonByteOffset + jsonByteLength, 2); | ||
const jsonChunkHeader = new Uint32Array(glb, 12, 2); | ||
const jsonByteOffset = 20; | ||
const jsonByteLength = jsonChunkHeader[0]; | ||
const binaryChunkHeader = new Uint32Array(glb, jsonByteOffset + jsonByteLength, 2); | ||
if (jsonChunkHeader[1] !== 0x4E4F534A || binaryChunkHeader[1] !== 0x004E4942) { | ||
@@ -364,9 +358,9 @@ throw new Error('Unexpected GLB layout.'); | ||
// Decode content. | ||
var jsonText = this.decodeText(glb.slice(jsonByteOffset, jsonByteOffset + jsonByteLength)); | ||
var json = JSON.parse(jsonText); | ||
var binaryByteOffset = jsonByteOffset + jsonByteLength + 8; | ||
var binaryByteLength = binaryChunkHeader[0]; | ||
var binary = glb.slice(binaryByteOffset, binaryByteOffset + binaryByteLength); | ||
const jsonText = this.decodeText(glb.slice(jsonByteOffset, jsonByteOffset + jsonByteLength)); | ||
const json = JSON.parse(jsonText); | ||
const binaryByteOffset = jsonByteOffset + jsonByteLength + 8; | ||
const binaryByteLength = binaryChunkHeader[0]; | ||
const binary = glb.slice(binaryByteOffset, binaryByteOffset + binaryByteLength); | ||
return new PackedGLTFContainer(json, binary).unpack(); | ||
}; | ||
} | ||
/** | ||
@@ -376,6 +370,6 @@ * Serializes a GLTFContainer to GLTF JSON and external files. | ||
*/ | ||
GLTFUtil.toGLTF = function (container) { | ||
var json = container.json, resources = container.resources; | ||
return { json: json, resources: resources }; | ||
}; | ||
static toGLTF(container) { | ||
const { json, resources } = container; | ||
return { json, resources }; | ||
} | ||
/** | ||
@@ -385,16 +379,16 @@ * Serializes a GLTFContainer to a GLB binary. | ||
*/ | ||
GLTFUtil.toGLB = function (container) { | ||
static toGLB(container) { | ||
if (container instanceof GLTFContainer) { | ||
container = PackedGLTFContainer.pack(container); | ||
} | ||
var jsonText = JSON.stringify(container.json); | ||
var jsonChunkData = this.pad(GLTFUtil.encodeText(jsonText), 0x20); | ||
var jsonChunkHeader = new Uint32Array([jsonChunkData.byteLength, 0x4E4F534A]).buffer; | ||
var jsonChunk = this.join(jsonChunkHeader, jsonChunkData); | ||
var binaryChunkData = this.pad(container.getBuffer(0), 0x00); | ||
var binaryChunkHeader = new Uint32Array([binaryChunkData.byteLength, 0x004E4942]).buffer; | ||
var binaryChunk = this.join(binaryChunkHeader, binaryChunkData); | ||
var header = new Uint32Array([0x46546C67, 2, 12 + jsonChunk.byteLength + binaryChunk.byteLength]).buffer; | ||
const jsonText = JSON.stringify(container.json); | ||
const jsonChunkData = this.pad(GLTFUtil.encodeText(jsonText), 0x20); | ||
const jsonChunkHeader = new Uint32Array([jsonChunkData.byteLength, 0x4E4F534A]).buffer; | ||
const jsonChunk = this.join(jsonChunkHeader, jsonChunkData); | ||
const binaryChunkData = this.pad(container.getBuffer(0), 0x00); | ||
const binaryChunkHeader = new Uint32Array([binaryChunkData.byteLength, 0x004E4942]).buffer; | ||
const binaryChunk = this.join(binaryChunkHeader, binaryChunkData); | ||
const header = new Uint32Array([0x46546C67, 2, 12 + jsonChunk.byteLength + binaryChunk.byteLength]).buffer; | ||
return this.join(this.join(header, jsonChunk), binaryChunk); | ||
}; | ||
} | ||
/** | ||
@@ -404,8 +398,8 @@ * Creates a buffer from a Data URI. | ||
*/ | ||
GLTFUtil.createBufferFromDataURI = function (dataURI) { | ||
static createBufferFromDataURI(dataURI) { | ||
if (typeof Buffer === 'undefined') { | ||
// Browser. | ||
var byteString = atob(dataURI.split(',')[1]); | ||
var ia = new Uint8Array(byteString.length); | ||
for (var i = 0; i < byteString.length; i++) { | ||
const byteString = atob(dataURI.split(',')[1]); | ||
const ia = new Uint8Array(byteString.length); | ||
for (let i = 0; i < byteString.length; i++) { | ||
ia[i] = byteString.charCodeAt(i); | ||
@@ -419,7 +413,7 @@ } | ||
} | ||
}; | ||
GLTFUtil.createLogger = function (name, verbosity) { | ||
} | ||
static createLogger(name, verbosity) { | ||
return new Logger(name, verbosity); | ||
}; | ||
GLTFUtil.encodeText = function (text) { | ||
} | ||
static encodeText(text) { | ||
if (typeof TextEncoder !== 'undefined') { | ||
@@ -429,17 +423,16 @@ return new TextEncoder().encode(text).buffer; | ||
return this.trimBuffer(Buffer.from(text)); | ||
}; | ||
GLTFUtil.decodeText = function (buffer) { | ||
} | ||
static decodeText(buffer) { | ||
if (typeof TextDecoder !== 'undefined') { | ||
return new TextDecoder().decode(buffer); | ||
} | ||
var a = Buffer.from(buffer); | ||
const a = Buffer.from(buffer); | ||
return a.toString('utf8'); | ||
}; | ||
GLTFUtil.trimBuffer = function (buffer) { | ||
var byteOffset = buffer.byteOffset, byteLength = buffer.byteLength; | ||
} | ||
static trimBuffer(buffer) { | ||
const { byteOffset, byteLength } = buffer; | ||
return buffer.buffer.slice(byteOffset, byteOffset + byteLength); | ||
}; | ||
GLTFUtil.analyze = function (container) { | ||
var _this = this; | ||
var report = { | ||
} | ||
static analyze(container) { | ||
const report = { | ||
meshes: (container.json.meshes || []).length, | ||
@@ -460,16 +453,16 @@ textures: (container.json.textures || []).length, | ||
// Primitives and targets. | ||
(container.json.meshes || []).forEach(function (mesh) { | ||
(container.json.meshes || []).forEach((mesh) => { | ||
report.primitives += mesh.primitives.length; | ||
mesh.primitives.forEach(function (primitive) { | ||
mesh.primitives.forEach((primitive) => { | ||
if (primitive.indices !== undefined) { | ||
report.dataUsage.geometry += _this.getAccessorByteLength(container.json.accessors[primitive.indices]); | ||
report.dataUsage.geometry += this.getAccessorByteLength(container.json.accessors[primitive.indices]); | ||
} | ||
Object.keys(primitive.attributes).forEach(function (attr) { | ||
var accessor = container.json.accessors[primitive.attributes[attr]]; | ||
report.dataUsage.geometry += _this.getAccessorByteLength(accessor); | ||
Object.keys(primitive.attributes).forEach((attr) => { | ||
const accessor = container.json.accessors[primitive.attributes[attr]]; | ||
report.dataUsage.geometry += this.getAccessorByteLength(accessor); | ||
}); | ||
(primitive.targets || []).forEach(function (target) { | ||
Object.keys(target).forEach(function (attr) { | ||
var accessor = container.json.accessors[target[attr]]; | ||
report.dataUsage.targets += _this.getAccessorByteLength(accessor); | ||
(primitive.targets || []).forEach((target) => { | ||
Object.keys(target).forEach((attr) => { | ||
const accessor = container.json.accessors[target[attr]]; | ||
report.dataUsage.targets += this.getAccessorByteLength(accessor); | ||
}); | ||
@@ -480,12 +473,12 @@ }); | ||
// Animation | ||
(container.json.animations || []).forEach(function (animation) { | ||
animation.samplers.forEach(function (sampler) { | ||
var input = container.json.accessors[sampler.input]; | ||
var output = container.json.accessors[sampler.output]; | ||
report.dataUsage.animation += _this.getAccessorByteLength(input); | ||
report.dataUsage.animation += _this.getAccessorByteLength(output); | ||
(container.json.animations || []).forEach((animation) => { | ||
animation.samplers.forEach((sampler) => { | ||
const input = container.json.accessors[sampler.input]; | ||
const output = container.json.accessors[sampler.output]; | ||
report.dataUsage.animation += this.getAccessorByteLength(input); | ||
report.dataUsage.animation += this.getAccessorByteLength(output); | ||
}); | ||
}); | ||
// Textures | ||
(container.json.images || []).forEach(function (image) { | ||
(container.json.images || []).forEach((image) => { | ||
if (image.uri !== undefined) { | ||
@@ -501,3 +494,3 @@ report.dataUsage.textures += container.resolveURI(image.uri).byteLength; | ||
return report; | ||
}; | ||
} | ||
/** | ||
@@ -510,21 +503,21 @@ * Adds a new image to the glTF container. | ||
*/ | ||
GLTFUtil.addImage = function (container, name, file, type) { | ||
var uri, mimeType; | ||
static addImage(container, name, file, type) { | ||
let uri, mimeType; | ||
switch (type) { | ||
case 'image/jpeg': | ||
uri = name + ".jpg"; | ||
uri = `${name}.jpg`; | ||
mimeType = 'image/jpeg'; | ||
break; | ||
case 'image/png': | ||
uri = name + ".png"; | ||
uri = `${name}.png`; | ||
mimeType = 'image/png'; | ||
break; | ||
default: | ||
throw new Error("Unsupported image type, \"" + type + "\"."); | ||
throw new Error(`Unsupported image type, "${type}".`); | ||
} | ||
container.json.images = container.json.images || []; | ||
container.json.images.push({ name: name, mimeType: mimeType, uri: uri }); | ||
container.json.images.push({ name, mimeType, uri }); | ||
container.resources[uri] = file; | ||
return container; | ||
}; | ||
} | ||
/** | ||
@@ -535,9 +528,9 @@ * Removes an image from the glTF container. Fails if image is still in use. | ||
*/ | ||
GLTFUtil.removeImage = function (container, index) { | ||
var textures = container.json.textures.filter(function (texture) { return texture.source === index; }); | ||
static removeImage(container, index) { | ||
const textures = container.json.textures.filter((texture) => texture.source === index); | ||
if (textures.length) { | ||
throw new Error("Image is in use by " + textures.length + " textures and cannot be removed."); | ||
throw new Error(`Image is in use by ${textures.length} textures and cannot be removed.`); | ||
} | ||
var image = container.json.images[index]; | ||
var imageBuffer = container.resolveURI(image.uri); | ||
const image = container.json.images[index]; | ||
const imageBuffer = container.resolveURI(image.uri); | ||
if (!imageBuffer) { | ||
@@ -547,3 +540,3 @@ throw new Error('No such image, or image is embedded.'); | ||
container.json.images.splice(index, 1); | ||
container.json.textures.forEach(function (texture) { | ||
container.json.textures.forEach((texture) => { | ||
if (texture.source > index) | ||
@@ -554,6 +547,6 @@ texture.source--; | ||
return container; | ||
}; | ||
GLTFUtil.getImageSize = function (container, index) { | ||
var image = container.json.images[index]; | ||
var isPNG; | ||
} | ||
static getImageSize(container, index) { | ||
const image = container.json.images[index]; | ||
let isPNG; | ||
if (image.mimeType) { | ||
@@ -565,7 +558,7 @@ isPNG = image.mimeType === 'image/png'; | ||
} | ||
var arrayBuffer = container.resolveURI(image.uri); | ||
const arrayBuffer = container.resolveURI(image.uri); | ||
return isPNG | ||
? getSizePNG(Buffer.from(arrayBuffer)) | ||
: getSizeJPEG(Buffer.from(arrayBuffer)); | ||
}; | ||
} | ||
/** | ||
@@ -576,4 +569,4 @@ * Removes a texture from the glTF container. | ||
*/ | ||
GLTFUtil.removeTexture = function (container, index) { | ||
container.json.materials.forEach(function (material) { | ||
static removeTexture(container, index) { | ||
container.json.materials.forEach((material) => { | ||
[ | ||
@@ -585,3 +578,3 @@ material.emissiveTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.metallicRoughnessTexture | ||
].forEach(function (texture) { | ||
].forEach((texture) => { | ||
if (texture.index === index) { | ||
@@ -597,3 +590,3 @@ throw new Error('Texture still in use.'); | ||
return container; | ||
}; | ||
} | ||
/** | ||
@@ -605,9 +598,9 @@ * Adds a new buffer to the glTF container. | ||
*/ | ||
GLTFUtil.addBuffer = function (container, name, arrayBuffer) { | ||
var uri = name + ".bin"; | ||
var buffer = { name: name, uri: uri, byteLength: arrayBuffer.byteLength }; | ||
static addBuffer(container, name, arrayBuffer) { | ||
const uri = `${name}.bin`; | ||
const buffer = { name, uri, byteLength: arrayBuffer.byteLength }; | ||
container.json.buffers.push(buffer); | ||
container.resources[uri] = arrayBuffer; | ||
return buffer; | ||
}; | ||
} | ||
/** | ||
@@ -618,11 +611,11 @@ * Removes a buffer from the glTF container. Fails if buffer is still in use. | ||
*/ | ||
GLTFUtil.removeBuffer = function (container, index) { | ||
var bufferViews = container.json.bufferViews.filter(function (view) { return view.buffer === index; }); | ||
static removeBuffer(container, index) { | ||
const bufferViews = container.json.bufferViews.filter((view) => view.buffer === index); | ||
if (bufferViews.length) { | ||
throw new Error("Buffer is in use by " + bufferViews.length + " bufferViews and cannot be removed."); | ||
throw new Error(`Buffer is in use by ${bufferViews.length} bufferViews and cannot be removed.`); | ||
} | ||
var buffer = container.json.buffers[index]; | ||
const buffer = container.json.buffers[index]; | ||
container.json.buffers.splice(index, 1); | ||
delete container.resources[buffer.uri]; | ||
container.json.bufferViews.forEach(function (bufferView) { | ||
container.json.bufferViews.forEach((bufferView) => { | ||
if (bufferView.buffer >= index) | ||
@@ -632,31 +625,30 @@ bufferView.buffer--; | ||
return buffer; | ||
}; | ||
GLTFUtil.addBufferView = function (container, arrayBuffer, bufferIndex) { | ||
if (bufferIndex === void 0) { bufferIndex = 0; } | ||
var buffer = container.json.buffers[bufferIndex]; | ||
var resource = container.getBuffer(bufferIndex); | ||
var byteOffset = resource.byteLength; | ||
} | ||
static addBufferView(container, arrayBuffer, bufferIndex = 0) { | ||
const buffer = container.json.buffers[bufferIndex]; | ||
let resource = container.getBuffer(bufferIndex); | ||
const byteOffset = resource.byteLength; | ||
resource = GLTFUtil.join(resource, arrayBuffer); | ||
container.setBuffer(bufferIndex, resource); | ||
buffer.byteLength = resource.byteLength; | ||
var bufferView = { buffer: bufferIndex, byteLength: arrayBuffer.byteLength, byteOffset: byteOffset }; | ||
const bufferView = { buffer: bufferIndex, byteLength: arrayBuffer.byteLength, byteOffset }; | ||
container.json.bufferViews.push(bufferView); | ||
return bufferView; | ||
}; | ||
} | ||
/** Removes bufferView, after checking to see whether it is used by any accessors. */ | ||
GLTFUtil.removeBufferView = function (container, bufferViewIndex) { | ||
var bufferView = container.json.bufferViews[bufferViewIndex]; | ||
var accessors = container.json.accessors.filter(function (accessor) { return accessor.bufferView === bufferViewIndex; }); | ||
static removeBufferView(container, bufferViewIndex) { | ||
const bufferView = container.json.bufferViews[bufferViewIndex]; | ||
const accessors = container.json.accessors.filter((accessor) => accessor.bufferView === bufferViewIndex); | ||
if (accessors.length) { | ||
throw new Error("Buffer is in use by " + accessors.length + " accessors and cannot be removed."); | ||
throw new Error(`Buffer is in use by ${accessors.length} accessors and cannot be removed.`); | ||
} | ||
if (bufferView.byteLength > 0) { | ||
var resource = container.getBuffer(bufferView.buffer); | ||
resource = this.splice(resource, bufferView.byteOffset, bufferView.byteLength)[0]; | ||
let resource = container.getBuffer(bufferView.buffer); | ||
[resource] = this.splice(resource, bufferView.byteOffset, bufferView.byteLength); | ||
container.setBuffer(bufferView.buffer, resource); | ||
var buffer = container.json.buffers[bufferView.buffer]; | ||
const buffer = container.json.buffers[bufferView.buffer]; | ||
buffer.byteLength -= bufferView.byteLength; | ||
container.json.bufferViews.forEach(function (bufferView) { | ||
if (bufferView.byteOffset > bufferView.byteOffset) { | ||
bufferView.byteOffset -= bufferView.byteLength; | ||
container.json.bufferViews.forEach((otherBufferView) => { | ||
if (otherBufferView.buffer === bufferView.buffer && otherBufferView.byteOffset > bufferView.byteOffset) { | ||
otherBufferView.byteOffset -= bufferView.byteLength; | ||
} | ||
@@ -666,3 +658,3 @@ }); | ||
container.json.bufferViews.splice(bufferViewIndex, 1); | ||
container.json.accessors.forEach(function (accessor) { | ||
container.json.accessors.forEach((accessor) => { | ||
if (accessor.bufferView > bufferViewIndex) | ||
@@ -672,16 +664,16 @@ accessor.bufferView--; | ||
return bufferView; | ||
}; | ||
GLTFUtil.addAccessor = function (container, array, type, componentType, count, target) { | ||
var bufferView = this.addBufferView(container, array.buffer, 0); | ||
} | ||
static addAccessor(container, array, type, componentType, count, target) { | ||
const bufferView = this.addBufferView(container, array.buffer, 0); | ||
bufferView['target'] = target; // TODO: Add to typings. | ||
var accessor = { | ||
const accessor = { | ||
bufferView: container.json.bufferViews.length - 1, | ||
byteOffset: 0, | ||
type: type, | ||
componentType: componentType, | ||
count: count | ||
type, | ||
componentType, | ||
count | ||
}; | ||
container.json.accessors.push(accessor); | ||
return accessor; | ||
}; | ||
} | ||
/** | ||
@@ -692,9 +684,9 @@ * Removes accessor, without checking to see whether it is used. | ||
*/ | ||
GLTFUtil.removeAccessor = function (container, index) { | ||
static removeAccessor(container, index) { | ||
if ((container.json.animations || []).length > 0) { | ||
throw new Error('Not implemented: cannot remove accessors from animated models.'); | ||
} | ||
var accessor = container.json.accessors[index]; | ||
var byteOffset = accessor.byteOffset || 0; | ||
var byteLength = GLTFUtil.getAccessorByteLength(accessor); | ||
const accessor = container.json.accessors[index]; | ||
const byteOffset = accessor.byteOffset || 0; | ||
const byteLength = GLTFUtil.getAccessorByteLength(accessor); | ||
if (byteLength) { | ||
@@ -706,3 +698,3 @@ this.spliceBufferView(container, accessor.bufferView, byteOffset, byteLength); | ||
// update byteOffset of other accessors | ||
container.json.accessors.forEach(function (otherAccessor) { | ||
container.json.accessors.forEach((otherAccessor) => { | ||
if (otherAccessor.bufferView === accessor.bufferView && (otherAccessor.byteOffset || 0) > byteOffset) { | ||
@@ -713,5 +705,5 @@ otherAccessor.byteOffset -= byteLength; | ||
// update pointers into following accessors | ||
container.json.meshes.forEach(function (mesh) { | ||
mesh.primitives.forEach(function (primitive) { | ||
for (var semantic in primitive.attributes) { | ||
container.json.meshes.forEach((mesh) => { | ||
mesh.primitives.forEach((primitive) => { | ||
for (let semantic in primitive.attributes) { | ||
if (primitive.attributes[semantic] === index) { | ||
@@ -733,3 +725,3 @@ throw new Error('Unexpected accessor use.'); | ||
return accessor; | ||
}; | ||
} | ||
/** | ||
@@ -741,12 +733,11 @@ * Removes data from a bufferView, updating other affected bufferviews. | ||
*/ | ||
GLTFUtil.spliceBufferView = function (container, bufferViewIndex, byteOffset, byteLength) { | ||
var _a; | ||
var bufferView = container.json.bufferViews[bufferViewIndex]; | ||
var bufferData = container.getBuffer(bufferView.buffer); | ||
var splicedData; | ||
_a = GLTFUtil.splice(bufferData, (bufferView.byteOffset || 0) + byteOffset, byteLength), bufferData = _a[0], splicedData = _a[1]; | ||
static spliceBufferView(container, bufferViewIndex, byteOffset, byteLength) { | ||
const bufferView = container.json.bufferViews[bufferViewIndex]; | ||
let bufferData = container.getBuffer(bufferView.buffer); | ||
let splicedData; | ||
[bufferData, splicedData] = GLTFUtil.splice(bufferData, (bufferView.byteOffset || 0) + byteOffset, byteLength); | ||
container.setBuffer(bufferView.buffer, bufferData); | ||
container.json.buffers[bufferView.buffer].byteLength -= byteLength; // TODO: do this when setBuffer is called? | ||
bufferView.byteLength -= byteLength; | ||
container.json.bufferViews.forEach(function (otherBufferView) { | ||
container.json.bufferViews.forEach((otherBufferView) => { | ||
if (bufferView.buffer === otherBufferView.buffer && (bufferView.byteOffset || 0) < (otherBufferView.byteOffset || 0)) { | ||
@@ -757,25 +748,25 @@ otherBufferView.byteOffset -= byteLength; | ||
return splicedData; | ||
}; | ||
GLTFUtil.getAccessorByteLength = function (accessor) { | ||
var itemSize = AccessorTypeData[accessor.type].size; | ||
var valueSize = AccessorComponentTypeData[accessor.componentType].size; | ||
} | ||
static getAccessorByteLength(accessor) { | ||
const itemSize = AccessorTypeData[accessor.type].size; | ||
const valueSize = AccessorComponentTypeData[accessor.componentType].size; | ||
return itemSize * valueSize * accessor.count; | ||
}; | ||
} | ||
/** | ||
* Removes segment from an arraybuffer, returning two arraybuffers: [original, removed]. | ||
*/ | ||
GLTFUtil.splice = function (buffer, begin, count) { | ||
var a1 = buffer.slice(0, begin); | ||
var a2 = buffer.slice(begin + count); | ||
var a = this.join(a1, a2); | ||
var b = buffer.slice(begin, begin + count); | ||
static splice(buffer, begin, count) { | ||
const a1 = buffer.slice(0, begin); | ||
const a2 = buffer.slice(begin + count); | ||
const a = this.join(a1, a2); | ||
const b = buffer.slice(begin, begin + count); | ||
return [a, b]; | ||
}; | ||
} | ||
/** Joins two ArrayBuffers. */ | ||
GLTFUtil.join = function (a, b) { | ||
var out = new Uint8Array(a.byteLength + b.byteLength); | ||
static join(a, b) { | ||
const out = new Uint8Array(a.byteLength + b.byteLength); | ||
out.set(new Uint8Array(a), 0); | ||
out.set(new Uint8Array(b), a.byteLength); | ||
return out.buffer; | ||
}; | ||
} | ||
/** | ||
@@ -785,3 +776,3 @@ * Pad buffer to the next 4-byte boundary. | ||
*/ | ||
GLTFUtil.pad = function (arrayBuffer, paddingByte) { | ||
static pad(arrayBuffer, paddingByte) { | ||
paddingByte = paddingByte || 0; | ||
@@ -800,4 +791,4 @@ var paddedLength = Math.ceil(arrayBuffer.byteLength / 4) * 4; | ||
return arrayBuffer; | ||
}; | ||
GLTFUtil.arrayBufferEquals = function (a, b) { | ||
} | ||
static arrayBufferEquals(a, b) { | ||
if (a === b) | ||
@@ -807,5 +798,5 @@ return true; | ||
return false; | ||
var view1 = new DataView(a); | ||
var view2 = new DataView(b); | ||
var i = a.byteLength; | ||
const view1 = new DataView(a); | ||
const view2 = new DataView(b); | ||
let i = a.byteLength; | ||
while (i--) { | ||
@@ -816,31 +807,29 @@ if (view1.getUint8(i) !== view2.getUint8(i)) | ||
return true; | ||
}; | ||
return GLTFUtil; | ||
}()); | ||
} | ||
} | ||
var NodeIO = /** @class */ (function () { | ||
function NodeIO(fs, path) { | ||
class NodeIO { | ||
constructor(fs, path) { | ||
this.fs = fs; | ||
this.path = path; | ||
} | ||
NodeIO.prototype.read = function (uri) { | ||
var isGLB = !!uri.match(/\.glb$/); | ||
read(uri) { | ||
const isGLB = !!uri.match(/\.glb$/); | ||
return isGLB ? this.readGLB(uri) : this.readGLTF(uri); | ||
}; | ||
NodeIO.prototype.readGLB = function (uri) { | ||
var buffer = this.fs.readFileSync(uri); | ||
var arrayBuffer = GLTFUtil.trimBuffer(buffer); | ||
} | ||
readGLB(uri) { | ||
const buffer = this.fs.readFileSync(uri); | ||
const arrayBuffer = GLTFUtil.trimBuffer(buffer); | ||
return GLTFUtil.fromGLB(arrayBuffer); | ||
}; | ||
NodeIO.prototype.readGLTF = function (uri) { | ||
var _this = this; | ||
var dir = this.path.dirname(uri); | ||
var json = JSON.parse(this.fs.readFileSync(uri, 'utf8')); | ||
var resources = {}; | ||
var images = json.images || []; | ||
var buffers = json.buffers || []; | ||
images.concat(buffers).forEach(function (resource) { | ||
} | ||
readGLTF(uri) { | ||
const dir = this.path.dirname(uri); | ||
const json = JSON.parse(this.fs.readFileSync(uri, 'utf8')); | ||
const resources = {}; | ||
const images = json.images || []; | ||
const buffers = json.buffers || []; | ||
[...images, ...buffers].forEach((resource) => { | ||
if (resource.uri && !resource.uri.match(/data:/)) { | ||
var absURI = _this.path.resolve(dir, resource.uri); | ||
resources[resource.uri] = GLTFUtil.trimBuffer(_this.fs.readFileSync(absURI)); | ||
const absURI = this.path.resolve(dir, resource.uri); | ||
resources[resource.uri] = GLTFUtil.trimBuffer(this.fs.readFileSync(absURI)); | ||
} | ||
@@ -852,46 +841,45 @@ else { | ||
return GLTFUtil.fromGLTF(json, resources); | ||
}; | ||
NodeIO.prototype.write = function (uri, container) { | ||
var isGLB = !!uri.match(/\.glb$/); | ||
} | ||
write(uri, container) { | ||
const isGLB = !!uri.match(/\.glb$/); | ||
isGLB ? this.writeGLB(uri, container) : this.writeGLTF(uri, container); | ||
}; | ||
NodeIO.prototype.writeGLTF = function (uri, container, embedded) { | ||
} | ||
writeGLTF(uri, container, embedded) { | ||
if (embedded) { | ||
throw new Error('Not implemented.'); | ||
} | ||
var _a = this, fs = _a.fs, path = _a.path; | ||
var dir = path.dirname(uri); | ||
var json = container.json, resources = container.resources; | ||
const { fs, path } = this; | ||
const dir = path.dirname(uri); | ||
const { json, resources } = container; | ||
fs.writeFileSync(uri, JSON.stringify(json)); | ||
Object.keys(resources).forEach(function (resourceName) { | ||
var resource = new Buffer(resources[resourceName]); | ||
Object.keys(resources).forEach((resourceName) => { | ||
const resource = new Buffer(resources[resourceName]); | ||
fs.writeFileSync(path.join(dir, resourceName), resource); | ||
}); | ||
}; | ||
NodeIO.prototype.writeGLB = function (uri, container) { | ||
var glbBuffer = GLTFUtil.toGLB(container); | ||
var buffer = Buffer.from(glbBuffer); | ||
} | ||
writeGLB(uri, container) { | ||
const glbBuffer = GLTFUtil.toGLB(container); | ||
const buffer = Buffer.from(glbBuffer); | ||
this.fs.writeFileSync(uri, buffer); | ||
}; | ||
return NodeIO; | ||
}()); | ||
var WebIO = /** @class */ (function () { | ||
function WebIO(fetchConfig) { | ||
} | ||
} | ||
class WebIO { | ||
constructor(fetchConfig) { | ||
this.fetchConfig = fetchConfig; | ||
} | ||
WebIO.prototype.read = function (uri) { | ||
var isGLB = !!uri.match(/\.glb$/); | ||
read(uri) { | ||
const isGLB = !!uri.match(/\.glb$/); | ||
return isGLB ? this.readGLB(uri) : this.readGLTF(uri); | ||
}; | ||
WebIO.prototype.readGLTF = function (uri) { | ||
var _this = this; | ||
} | ||
readGLTF(uri) { | ||
return fetch(uri, this.fetchConfig) | ||
.then(function (response) { return response.json(); }) | ||
.then(function (json) { | ||
var resources = {}; | ||
var pendingResources = json.images.concat(json.buffers).map(function (resource) { | ||
.then((response) => response.json()) | ||
.then((json) => { | ||
const resources = {}; | ||
const pendingResources = [...json.images, ...json.buffers] | ||
.map((resource) => { | ||
if (resource.uri) { | ||
return fetch(resource.uri, _this.fetchConfig) | ||
.then(function (response) { return response.arrayBuffer(); }) | ||
.then(function (arrayBuffer) { | ||
return fetch(resource.uri, this.fetchConfig) | ||
.then((response) => response.arrayBuffer()) | ||
.then((arrayBuffer) => { | ||
resources[resource.uri] = arrayBuffer; | ||
@@ -905,12 +893,11 @@ }); | ||
return Promise.all(pendingResources) | ||
.then(function () { return GLTFUtil.fromGLTF(json, resources); }); | ||
.then(() => GLTFUtil.fromGLTF(json, resources)); | ||
}); | ||
}; | ||
WebIO.prototype.readGLB = function (uri) { | ||
} | ||
readGLB(uri) { | ||
return fetch(uri, this.fetchConfig) | ||
.then(function (response) { return response.arrayBuffer(); }) | ||
.then(function (arrayBuffer) { return GLTFUtil.fromGLB(arrayBuffer); }); | ||
}; | ||
return WebIO; | ||
}()); | ||
.then((response) => response.arrayBuffer()) | ||
.then((arrayBuffer) => GLTFUtil.fromGLB(arrayBuffer)); | ||
} | ||
} | ||
@@ -917,0 +904,0 @@ exports.GLTFUtil = GLTFUtil; |
{ | ||
"name": "@gltf-transform/core", | ||
"version": "0.0.14", | ||
"version": "0.1.0", | ||
"repository": "github:donmccurdy/glTF-Transform", | ||
@@ -28,3 +28,3 @@ "description": "JavaScript and TypeScript utilities for processing glTF 3D models", | ||
], | ||
"gitHead": "0737e8fe1ca770cd98637f2daf9b02ac099d57a5" | ||
"gitHead": "c6fa67080f7863f4ed79560ab1b812ccd8a73fbe" | ||
} |
@@ -353,5 +353,5 @@ import { AccessorComponentTypeData, AccessorTypeData } from './constants'; | ||
container.json.bufferViews.forEach((bufferView) => { | ||
if (bufferView.byteOffset > bufferView.byteOffset) { | ||
bufferView.byteOffset -= bufferView.byteLength; | ||
container.json.bufferViews.forEach((otherBufferView) => { | ||
if (otherBufferView.buffer === bufferView.buffer && otherBufferView.byteOffset > bufferView.byteOffset) { | ||
otherBufferView.byteOffset -= bufferView.byteLength; | ||
} | ||
@@ -358,0 +358,0 @@ }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
150377
25
3728