@gltf-transform/core
Advanced tools
Comparing version 0.0.7 to 0.0.10
@@ -106,21 +106,11 @@ 'use strict'; | ||
var start = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0); | ||
var elementSize; | ||
var data; | ||
switch (accessor.componentType) { | ||
case AccessorComponentType.FLOAT: | ||
elementSize = Float32Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Float32Array(data); | ||
return new Float32Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_INT: | ||
elementSize = Uint32Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint32Array(data); | ||
return new Uint32Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_SHORT: | ||
elementSize = Uint16Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint16Array(data); | ||
return new Uint16Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_BYTE: | ||
elementSize = Uint8Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint8Array(data); | ||
return new Uint8Array(resource, start, accessor.count * valueSize); | ||
default: | ||
@@ -165,3 +155,3 @@ throw new Error("Accessor componentType " + accessor.componentType + " not implemented."); | ||
Logger.prototype.info = function (text) { | ||
if (this.verbosity >= exports.LoggerVerbosity.INFO) { | ||
if (this.verbosity <= exports.LoggerVerbosity.INFO) { | ||
console.log(this.name + ": " + text); | ||
@@ -175,3 +165,3 @@ } | ||
Logger.prototype.warn = function (text) { | ||
if (this.verbosity >= exports.LoggerVerbosity.WARNING) { | ||
if (this.verbosity <= exports.LoggerVerbosity.WARNING) { | ||
console.warn(this.name + ": " + text); | ||
@@ -185,3 +175,3 @@ } | ||
Logger.prototype.error = function (text) { | ||
if (this.verbosity >= exports.LoggerVerbosity.ERROR) { | ||
if (this.verbosity <= exports.LoggerVerbosity.ERROR) { | ||
console.error(this.name + ": " + text); | ||
@@ -264,2 +254,55 @@ } | ||
//////////////////////////////////////////////////////// | ||
function extractSize(buffer, i) { | ||
return { | ||
'height': buffer.readUInt16BE(i), | ||
'width': buffer.readUInt16BE(i + 2) | ||
}; | ||
} | ||
function validateBuffer(buffer, i) { | ||
// index should be within buffer limits | ||
if (i > buffer.length) { | ||
throw new TypeError('Corrupt JPG, exceeded buffer limits'); | ||
} | ||
// Every JPEG block must begin with a 0xFF | ||
if (buffer[i] !== 0xFF) { | ||
throw new TypeError('Invalid JPG, marker table corrupted'); | ||
} | ||
} | ||
function getSizeJPEG(buffer) { | ||
// Skip 4 chars, they are for signature | ||
buffer = buffer.slice(4); | ||
var i, next; | ||
while (buffer.length) { | ||
// read length of the next block | ||
i = buffer.readUInt16BE(0); | ||
// ensure correct format | ||
validateBuffer(buffer, i); | ||
// 0xFFC0 is baseline standard(SOF) | ||
// 0xFFC1 is baseline optimized(SOF) | ||
// 0xFFC2 is progressive(SOF2) | ||
next = buffer[i + 1]; | ||
if (next === 0xC0 || next === 0xC1 || next === 0xC2) { | ||
return extractSize(buffer, i + 5); | ||
} | ||
// move to the next block | ||
buffer = buffer.slice(i + 2); | ||
} | ||
throw new TypeError('Invalid JPG, no size found'); | ||
} | ||
// Used to detect "fried" png's: http://www.jongware.com/pngdefry.html | ||
var pngFriedChunkName = 'CgBI'; | ||
function getSizePNG(buffer) { | ||
if (buffer.toString('ascii', 12, 16) === pngFriedChunkName) { | ||
return { | ||
width: buffer.readUInt32BE(32), | ||
height: buffer.readUInt32BE(36) | ||
}; | ||
} | ||
return { | ||
width: buffer.readUInt32BE(16), | ||
height: buffer.readUInt32BE(20) | ||
}; | ||
} | ||
/** | ||
@@ -300,3 +343,3 @@ * Utility class for glTF transforms. | ||
} | ||
// Decode content. | ||
// Decode content. | ||
var jsonText = this.decodeText(glb.slice(jsonByteOffset, jsonByteOffset + jsonByteLength)); | ||
@@ -379,2 +422,3 @@ var json = JSON.parse(jsonText); | ||
textures: (container.json.textures || []).length, | ||
images: (container.json.images || []).length, | ||
materials: (container.json.materials || []).length, | ||
@@ -478,5 +522,45 @@ animations: (container.json.animations || []).length, | ||
}); | ||
delete container.resources[image.uri]; | ||
return container; | ||
}; | ||
GLTFUtil.getImageSize = function (container, index) { | ||
var image = container.json.images[index]; | ||
var isPNG; | ||
if (image.mimeType) { | ||
isPNG = image.mimeType === 'image/png'; | ||
} | ||
else { | ||
isPNG = image.uri.match(/\.png$/); | ||
} | ||
var arrayBuffer = container.resolveURI(image.uri); | ||
return isPNG | ||
? getSizePNG(Buffer.from(arrayBuffer)) | ||
: getSizeJPEG(Buffer.from(arrayBuffer)); | ||
}; | ||
/** | ||
* Removes a texture from the glTF container. | ||
* @param container | ||
* @param index | ||
*/ | ||
GLTFUtil.removeTexture = function (container, index) { | ||
container.json.materials.forEach(function (material) { | ||
[ | ||
material.emissiveTexture, | ||
material.normalTexture, | ||
material.occlusionTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.baseColorTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.metallicRoughnessTexture | ||
].forEach(function (texture) { | ||
if (texture.index === index) { | ||
throw new Error('Texture still in use.'); | ||
} | ||
else if (texture.index > index) { | ||
texture.index--; | ||
} | ||
}); | ||
}); | ||
container.json.textures.splice(index, 1); | ||
return container; | ||
}; | ||
/** | ||
* Adds a new buffer to the glTF container. | ||
@@ -483,0 +567,0 @@ * @param container |
@@ -102,21 +102,11 @@ var AccessorType = { | ||
var start = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0); | ||
var elementSize; | ||
var data; | ||
switch (accessor.componentType) { | ||
case AccessorComponentType.FLOAT: | ||
elementSize = Float32Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Float32Array(data); | ||
return new Float32Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_INT: | ||
elementSize = Uint32Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint32Array(data); | ||
return new Uint32Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_SHORT: | ||
elementSize = Uint16Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint16Array(data); | ||
return new Uint16Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_BYTE: | ||
elementSize = Uint8Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint8Array(data); | ||
return new Uint8Array(resource, start, accessor.count * valueSize); | ||
default: | ||
@@ -162,3 +152,3 @@ throw new Error("Accessor componentType " + accessor.componentType + " not implemented."); | ||
Logger.prototype.info = function (text) { | ||
if (this.verbosity >= LoggerVerbosity.INFO) { | ||
if (this.verbosity <= LoggerVerbosity.INFO) { | ||
console.log(this.name + ": " + text); | ||
@@ -172,3 +162,3 @@ } | ||
Logger.prototype.warn = function (text) { | ||
if (this.verbosity >= LoggerVerbosity.WARNING) { | ||
if (this.verbosity <= LoggerVerbosity.WARNING) { | ||
console.warn(this.name + ": " + text); | ||
@@ -182,3 +172,3 @@ } | ||
Logger.prototype.error = function (text) { | ||
if (this.verbosity >= LoggerVerbosity.ERROR) { | ||
if (this.verbosity <= LoggerVerbosity.ERROR) { | ||
console.error(this.name + ": " + text); | ||
@@ -261,2 +251,55 @@ } | ||
//////////////////////////////////////////////////////// | ||
function extractSize(buffer, i) { | ||
return { | ||
'height': buffer.readUInt16BE(i), | ||
'width': buffer.readUInt16BE(i + 2) | ||
}; | ||
} | ||
function validateBuffer(buffer, i) { | ||
// index should be within buffer limits | ||
if (i > buffer.length) { | ||
throw new TypeError('Corrupt JPG, exceeded buffer limits'); | ||
} | ||
// Every JPEG block must begin with a 0xFF | ||
if (buffer[i] !== 0xFF) { | ||
throw new TypeError('Invalid JPG, marker table corrupted'); | ||
} | ||
} | ||
function getSizeJPEG(buffer) { | ||
// Skip 4 chars, they are for signature | ||
buffer = buffer.slice(4); | ||
var i, next; | ||
while (buffer.length) { | ||
// read length of the next block | ||
i = buffer.readUInt16BE(0); | ||
// ensure correct format | ||
validateBuffer(buffer, i); | ||
// 0xFFC0 is baseline standard(SOF) | ||
// 0xFFC1 is baseline optimized(SOF) | ||
// 0xFFC2 is progressive(SOF2) | ||
next = buffer[i + 1]; | ||
if (next === 0xC0 || next === 0xC1 || next === 0xC2) { | ||
return extractSize(buffer, i + 5); | ||
} | ||
// move to the next block | ||
buffer = buffer.slice(i + 2); | ||
} | ||
throw new TypeError('Invalid JPG, no size found'); | ||
} | ||
// Used to detect "fried" png's: http://www.jongware.com/pngdefry.html | ||
var pngFriedChunkName = 'CgBI'; | ||
function getSizePNG(buffer) { | ||
if (buffer.toString('ascii', 12, 16) === pngFriedChunkName) { | ||
return { | ||
width: buffer.readUInt32BE(32), | ||
height: buffer.readUInt32BE(36) | ||
}; | ||
} | ||
return { | ||
width: buffer.readUInt32BE(16), | ||
height: buffer.readUInt32BE(20) | ||
}; | ||
} | ||
/** | ||
@@ -297,3 +340,3 @@ * Utility class for glTF transforms. | ||
} | ||
// Decode content. | ||
// Decode content. | ||
var jsonText = this.decodeText(glb.slice(jsonByteOffset, jsonByteOffset + jsonByteLength)); | ||
@@ -376,2 +419,3 @@ var json = JSON.parse(jsonText); | ||
textures: (container.json.textures || []).length, | ||
images: (container.json.images || []).length, | ||
materials: (container.json.materials || []).length, | ||
@@ -475,5 +519,45 @@ animations: (container.json.animations || []).length, | ||
}); | ||
delete container.resources[image.uri]; | ||
return container; | ||
}; | ||
GLTFUtil.getImageSize = function (container, index) { | ||
var image = container.json.images[index]; | ||
var isPNG; | ||
if (image.mimeType) { | ||
isPNG = image.mimeType === 'image/png'; | ||
} | ||
else { | ||
isPNG = image.uri.match(/\.png$/); | ||
} | ||
var arrayBuffer = container.resolveURI(image.uri); | ||
return isPNG | ||
? getSizePNG(Buffer.from(arrayBuffer)) | ||
: getSizeJPEG(Buffer.from(arrayBuffer)); | ||
}; | ||
/** | ||
* Removes a texture from the glTF container. | ||
* @param container | ||
* @param index | ||
*/ | ||
GLTFUtil.removeTexture = function (container, index) { | ||
container.json.materials.forEach(function (material) { | ||
[ | ||
material.emissiveTexture, | ||
material.normalTexture, | ||
material.occlusionTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.baseColorTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.metallicRoughnessTexture | ||
].forEach(function (texture) { | ||
if (texture.index === index) { | ||
throw new Error('Texture still in use.'); | ||
} | ||
else if (texture.index > index) { | ||
texture.index--; | ||
} | ||
}); | ||
}); | ||
container.json.textures.splice(index, 1); | ||
return container; | ||
}; | ||
/** | ||
* Adds a new buffer to the glTF container. | ||
@@ -480,0 +564,0 @@ * @param container |
@@ -108,21 +108,11 @@ (function (global, factory) { | ||
var start = (bufferView.byteOffset || 0) + (accessor.byteOffset || 0); | ||
var elementSize; | ||
var data; | ||
switch (accessor.componentType) { | ||
case AccessorComponentType.FLOAT: | ||
elementSize = Float32Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Float32Array(data); | ||
return new Float32Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_INT: | ||
elementSize = Uint32Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint32Array(data); | ||
return new Uint32Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_SHORT: | ||
elementSize = Uint16Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint16Array(data); | ||
return new Uint16Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_BYTE: | ||
elementSize = Uint8Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint8Array(data); | ||
return new Uint8Array(resource, start, accessor.count * valueSize); | ||
default: | ||
@@ -167,3 +157,3 @@ throw new Error("Accessor componentType " + accessor.componentType + " not implemented."); | ||
Logger.prototype.info = function (text) { | ||
if (this.verbosity >= exports.LoggerVerbosity.INFO) { | ||
if (this.verbosity <= exports.LoggerVerbosity.INFO) { | ||
console.log(this.name + ": " + text); | ||
@@ -177,3 +167,3 @@ } | ||
Logger.prototype.warn = function (text) { | ||
if (this.verbosity >= exports.LoggerVerbosity.WARNING) { | ||
if (this.verbosity <= exports.LoggerVerbosity.WARNING) { | ||
console.warn(this.name + ": " + text); | ||
@@ -187,3 +177,3 @@ } | ||
Logger.prototype.error = function (text) { | ||
if (this.verbosity >= exports.LoggerVerbosity.ERROR) { | ||
if (this.verbosity <= exports.LoggerVerbosity.ERROR) { | ||
console.error(this.name + ": " + text); | ||
@@ -266,2 +256,55 @@ } | ||
//////////////////////////////////////////////////////// | ||
function extractSize(buffer, i) { | ||
return { | ||
'height': buffer.readUInt16BE(i), | ||
'width': buffer.readUInt16BE(i + 2) | ||
}; | ||
} | ||
function validateBuffer(buffer, i) { | ||
// index should be within buffer limits | ||
if (i > buffer.length) { | ||
throw new TypeError('Corrupt JPG, exceeded buffer limits'); | ||
} | ||
// Every JPEG block must begin with a 0xFF | ||
if (buffer[i] !== 0xFF) { | ||
throw new TypeError('Invalid JPG, marker table corrupted'); | ||
} | ||
} | ||
function getSizeJPEG(buffer) { | ||
// Skip 4 chars, they are for signature | ||
buffer = buffer.slice(4); | ||
var i, next; | ||
while (buffer.length) { | ||
// read length of the next block | ||
i = buffer.readUInt16BE(0); | ||
// ensure correct format | ||
validateBuffer(buffer, i); | ||
// 0xFFC0 is baseline standard(SOF) | ||
// 0xFFC1 is baseline optimized(SOF) | ||
// 0xFFC2 is progressive(SOF2) | ||
next = buffer[i + 1]; | ||
if (next === 0xC0 || next === 0xC1 || next === 0xC2) { | ||
return extractSize(buffer, i + 5); | ||
} | ||
// move to the next block | ||
buffer = buffer.slice(i + 2); | ||
} | ||
throw new TypeError('Invalid JPG, no size found'); | ||
} | ||
// Used to detect "fried" png's: http://www.jongware.com/pngdefry.html | ||
var pngFriedChunkName = 'CgBI'; | ||
function getSizePNG(buffer) { | ||
if (buffer.toString('ascii', 12, 16) === pngFriedChunkName) { | ||
return { | ||
width: buffer.readUInt32BE(32), | ||
height: buffer.readUInt32BE(36) | ||
}; | ||
} | ||
return { | ||
width: buffer.readUInt32BE(16), | ||
height: buffer.readUInt32BE(20) | ||
}; | ||
} | ||
/** | ||
@@ -302,3 +345,3 @@ * Utility class for glTF transforms. | ||
} | ||
// Decode content. | ||
// Decode content. | ||
var jsonText = this.decodeText(glb.slice(jsonByteOffset, jsonByteOffset + jsonByteLength)); | ||
@@ -381,2 +424,3 @@ var json = JSON.parse(jsonText); | ||
textures: (container.json.textures || []).length, | ||
images: (container.json.images || []).length, | ||
materials: (container.json.materials || []).length, | ||
@@ -480,5 +524,45 @@ animations: (container.json.animations || []).length, | ||
}); | ||
delete container.resources[image.uri]; | ||
return container; | ||
}; | ||
GLTFUtil.getImageSize = function (container, index) { | ||
var image = container.json.images[index]; | ||
var isPNG; | ||
if (image.mimeType) { | ||
isPNG = image.mimeType === 'image/png'; | ||
} | ||
else { | ||
isPNG = image.uri.match(/\.png$/); | ||
} | ||
var arrayBuffer = container.resolveURI(image.uri); | ||
return isPNG | ||
? getSizePNG(Buffer.from(arrayBuffer)) | ||
: getSizeJPEG(Buffer.from(arrayBuffer)); | ||
}; | ||
/** | ||
* Removes a texture from the glTF container. | ||
* @param container | ||
* @param index | ||
*/ | ||
GLTFUtil.removeTexture = function (container, index) { | ||
container.json.materials.forEach(function (material) { | ||
[ | ||
material.emissiveTexture, | ||
material.normalTexture, | ||
material.occlusionTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.baseColorTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.metallicRoughnessTexture | ||
].forEach(function (texture) { | ||
if (texture.index === index) { | ||
throw new Error('Texture still in use.'); | ||
} | ||
else if (texture.index > index) { | ||
texture.index--; | ||
} | ||
}); | ||
}); | ||
container.json.textures.splice(index, 1); | ||
return container; | ||
}; | ||
/** | ||
* Adds a new buffer to the glTF container. | ||
@@ -485,0 +569,0 @@ * @param container |
/// <reference types="node" /> | ||
import { GLTFContainer, IBufferMap, IContainer } from './container'; | ||
import { Logger, LoggerVerbosity } from './logger'; | ||
import { ISize } from './image-util'; | ||
interface IGLTFAnalysis { | ||
@@ -70,3 +71,10 @@ meshes: number; | ||
static removeImage(container: GLTFContainer, index: number): GLTFContainer; | ||
static getImageSize(container: GLTFContainer, index: number): ISize; | ||
/** | ||
* Removes a texture from the glTF container. | ||
* @param container | ||
* @param index | ||
*/ | ||
static removeTexture(container: GLTFContainer, index: number): GLTFContainer; | ||
/** | ||
* Adds a new buffer to the glTF container. | ||
@@ -73,0 +81,0 @@ * @param container |
{ | ||
"name": "@gltf-transform/core", | ||
"version": "0.0.4", | ||
"version": "0.0.7", | ||
"lockfileVersion": 1 | ||
} |
{ | ||
"name": "@gltf-transform/core", | ||
"version": "0.0.7", | ||
"version": "0.0.10", | ||
"repository": "github:donmccurdy/glTF-Transform", | ||
@@ -27,3 +27,4 @@ "description": "JavaScript and TypeScript utilities for processing glTF 3D models", | ||
"package-lock.json" | ||
] | ||
], | ||
"gitHead": "98dfd76f6d6396c7d46116350648c0705b9fce83" | ||
} |
@@ -79,21 +79,11 @@ import { AccessorTypeData, AccessorComponentType } from './constants'; | ||
let elementSize; | ||
let data; | ||
switch (accessor.componentType) { | ||
case AccessorComponentType.FLOAT: | ||
elementSize = Float32Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Float32Array(data); | ||
return new Float32Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_INT: | ||
elementSize = Uint32Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint32Array(data); | ||
return new Uint32Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_SHORT: | ||
elementSize = Uint16Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint16Array(data); | ||
case AccessorComponentType.UNSIGNED_BYTE: | ||
elementSize = Uint8Array.BYTES_PER_ELEMENT; | ||
data = resource.slice(start, start + accessor.count * valueSize * elementSize); | ||
return new Uint8Array(data); | ||
return new Uint16Array(resource, start, accessor.count * valueSize); | ||
case AccessorComponentType.UNSIGNED_BYTE: | ||
return new Uint8Array(resource, start, accessor.count * valueSize); | ||
default: | ||
@@ -100,0 +90,0 @@ throw new Error(`Accessor componentType ${accessor.componentType} not implemented.`); |
@@ -19,3 +19,3 @@ enum LoggerVerbosity { | ||
info (text: string) { | ||
if (this.verbosity >= LoggerVerbosity.INFO) { | ||
if (this.verbosity <= LoggerVerbosity.INFO) { | ||
console.log(`${this.name}: ${text}`); | ||
@@ -30,3 +30,3 @@ } | ||
warn (text: string) { | ||
if (this.verbosity >= LoggerVerbosity.WARNING) { | ||
if (this.verbosity <= LoggerVerbosity.WARNING) { | ||
console.warn(`${this.name}: ${text}`); | ||
@@ -41,3 +41,3 @@ } | ||
error (text: string) { | ||
if (this.verbosity >= LoggerVerbosity.ERROR) { | ||
if (this.verbosity <= LoggerVerbosity.ERROR) { | ||
console.error(`${this.name}: ${text}`); | ||
@@ -44,0 +44,0 @@ } |
@@ -5,2 +5,3 @@ import { AccessorComponentTypeData, AccessorTypeData } from './constants'; | ||
import { PackedGLTFContainer } from './packed-container'; | ||
import { getSizeJPEG, getSizePNG, ISize } from './image-util'; | ||
@@ -57,3 +58,3 @@ interface IGLTFAnalysis { | ||
// Decode content. | ||
// Decode content. | ||
const jsonText = this.decodeText(glb.slice(jsonByteOffset, jsonByteOffset + jsonByteLength)); | ||
@@ -133,3 +134,3 @@ const json = JSON.parse(jsonText) as GLTF.IGLTF; | ||
} | ||
const a = Buffer.from(buffer) as any; | ||
const a = Buffer.from(buffer) as any; | ||
return a.toString('utf8'); | ||
@@ -147,2 +148,3 @@ } | ||
textures: (container.json.textures||[]).length, | ||
images: (container.json.images||[]).length, | ||
materials: (container.json.materials||[]).length, | ||
@@ -252,6 +254,46 @@ animations: (container.json.animations||[]).length, | ||
}); | ||
delete container.resources[image.uri]; | ||
return container; | ||
} | ||
static getImageSize(container: GLTFContainer, index: number): ISize { | ||
const image = container.json.images[index]; | ||
let isPNG; | ||
if (image.mimeType) { | ||
isPNG = image.mimeType === 'image/png'; | ||
} else { | ||
isPNG = image.uri.match(/\.png$/); | ||
} | ||
const arrayBuffer = container.resolveURI(image.uri); | ||
return isPNG | ||
? getSizePNG(Buffer.from(arrayBuffer)) | ||
: getSizeJPEG(Buffer.from(arrayBuffer)); | ||
} | ||
/** | ||
* Removes a texture from the glTF container. | ||
* @param container | ||
* @param index | ||
*/ | ||
static removeTexture(container: GLTFContainer, index: number): GLTFContainer { | ||
container.json.materials.forEach((material) => { | ||
[ | ||
material.emissiveTexture, | ||
material.normalTexture, | ||
material.occlusionTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.baseColorTexture, | ||
material.pbrMetallicRoughness && material.pbrMetallicRoughness.metallicRoughnessTexture | ||
].forEach((texture) => { | ||
if (texture.index === index) { | ||
throw new Error('Texture still in use.'); | ||
} else if (texture.index > index) { | ||
texture.index--; | ||
} | ||
}); | ||
}); | ||
container.json.textures.splice(index, 1); | ||
return container; | ||
} | ||
/** | ||
* Adds a new buffer to the glTF container. | ||
@@ -332,3 +374,3 @@ * @param container | ||
static addAccessor( | ||
container: GLTFContainer, | ||
container: GLTFContainer, | ||
array: Float32Array | Uint32Array | Uint16Array, | ||
@@ -354,10 +396,10 @@ type: GLTF.AccessorType, | ||
* Removes accessor, without checking to see whether it is used. | ||
* | ||
* | ||
* - NOTE: Cannot currently update nonmesh accessors, which will lead to bugs. | ||
*/ | ||
static removeAccessor(container: GLTFContainer, index: number): GLTF.IAccessor { | ||
static removeAccessor(container: GLTFContainer, index: number): GLTF.IAccessor { | ||
if ((container.json.animations||[]).length > 0) { | ||
throw new Error('Not implemented: cannot remove accessors from animated models.'); | ||
} | ||
const accessor = container.json.accessors[index]; | ||
@@ -457,22 +499,22 @@ const byteOffset = accessor.byteOffset || 0; | ||
var paddedLength = Math.ceil( arrayBuffer.byteLength / 4 ) * 4; | ||
if ( paddedLength !== arrayBuffer.byteLength ) { | ||
var array = new Uint8Array( paddedLength ); | ||
array.set( new Uint8Array( arrayBuffer ) ); | ||
if ( paddingByte !== 0 ) { | ||
for ( var i = arrayBuffer.byteLength; i < paddedLength; i ++ ) { | ||
array[ i ] = paddingByte; | ||
} | ||
} | ||
return array.buffer; | ||
} | ||
return arrayBuffer; | ||
@@ -479,0 +521,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
156848
26
3772