@openhps/core
Version:
Open Hybrid Positioning System - Core component
120 lines (115 loc) • 4.43 kB
JavaScript
import { LinearFilter } from '../constants.js';
import { FileLoader } from './FileLoader.js';
import { CompressedTexture } from '../textures/CompressedTexture.js';
import { Loader } from './Loader.js';
/**
* Abstract base class for loading compressed texture formats S3TC, ASTC or ETC.
* Textures are internally loaded via {@link FileLoader}.
*
* Derived classes have to implement the `parse()` method which holds the parsing
* for the respective format.
*
* @abstract
* @augments Loader
*/
class CompressedTextureLoader extends Loader {
/**
* Constructs a new compressed texture loader.
*
* @param {LoadingManager} [manager] - The loading manager.
*/
constructor(manager) {
super(manager);
}
/**
* Starts loading from the given URL and passes the loaded compressed texture
* to the `onLoad()` callback. The method also returns a new texture object which can
* directly be used for material creation. If you do it this way, the texture
* may pop up in your scene once the respective loading process is finished.
*
* @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
* @param {function(CompressedTexture)} onLoad - Executed when the loading process has been finished.
* @param {onProgressCallback} onProgress - Executed while the loading is in progress.
* @param {onErrorCallback} onError - Executed when errors occur.
* @return {CompressedTexture} The compressed texture.
*/
load(url, onLoad, onProgress, onError) {
const scope = this;
const images = [];
const texture = new CompressedTexture();
const loader = new FileLoader(this.manager);
loader.setPath(this.path);
loader.setResponseType('arraybuffer');
loader.setRequestHeader(this.requestHeader);
loader.setWithCredentials(scope.withCredentials);
let loaded = 0;
function loadTexture(i) {
loader.load(url[i], function (buffer) {
const texDatas = scope.parse(buffer, true);
images[i] = {
width: texDatas.width,
height: texDatas.height,
format: texDatas.format,
mipmaps: texDatas.mipmaps
};
loaded += 1;
if (loaded === 6) {
if (texDatas.mipmapCount === 1) texture.minFilter = LinearFilter;
texture.image = images;
texture.format = texDatas.format;
texture.needsUpdate = true;
if (onLoad) onLoad(texture);
}
}, onProgress, onError);
}
if (Array.isArray(url)) {
for (let i = 0, il = url.length; i < il; ++i) {
loadTexture(i);
}
} else {
// compressed cubemap texture stored in a single DDS file
loader.load(url, function (buffer) {
const texDatas = scope.parse(buffer, true);
if (texDatas.isCubemap) {
const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
for (let f = 0; f < faces; f++) {
images[f] = {
mipmaps: []
};
for (let i = 0; i < texDatas.mipmapCount; i++) {
images[f].mipmaps.push(texDatas.mipmaps[f * texDatas.mipmapCount + i]);
images[f].format = texDatas.format;
images[f].width = texDatas.width;
images[f].height = texDatas.height;
}
}
texture.image = images;
} else {
texture.image.width = texDatas.width;
texture.image.height = texDatas.height;
texture.mipmaps = texDatas.mipmaps;
}
if (texDatas.mipmapCount === 1) {
texture.minFilter = LinearFilter;
}
texture.format = texDatas.format;
texture.needsUpdate = true;
if (onLoad) onLoad(texture);
}, onProgress, onError);
}
return texture;
}
}
/**
* Represents the result object type of the `parse()` method.
*
* @typedef {Object} CompressedTextureLoader~TexData
* @property {number} width - The width of the base mip.
* @property {number} height - The width of the base mip.
* @property {boolean} isCubemap - Whether the data represent a cubemap or not.
* @property {number} mipmapCount - The mipmap count.
* @property {Array<{data:TypedArray,width:number,height:number}>} mipmaps - An array holding the mipmaps.
* Each entry holds the data and the dimensions for each level.
* @property {number} format - The texture format.
**/
export { CompressedTextureLoader };