TextureLODsDownloader

Introduction

vtkTextureLODsDownloader provides a way to download textures by bulk.

Methods

extend

Method used to decorate a given object (publicAPI+model) with vtkTextureLODsDownloader characteristics.

Argument Type Required Description
publicAPI Yes object on which methods will be bounds (public)
model Yes object on which data structure will be bounds (protected)
initialValues ITextureLODsDownloaderInitialValues No (default: {})

getBaseUrl

Get the base of the url

getCrossOrigin

Get the crossorigin attribute

getFiles

Get the list of files to download

getMaxTextureLODSize

Get the max texture LOD size

getStepFinishedCallback

getTexture

Get the vtkTexture object

getWaitTimeBetweenDownloads

Get the delay between downloads

getWaitTimeToStart

Get the delay before the start of download.

newInstance

Method used to create a new instance of vtkTextureLODsDownloader

Argument Type Required Description
initialValues ITextureLODsDownloaderInitialValues No for pre-setting some of its content

setBaseUrl

Set the base of the url

Argument Type Required Description
baseUrl String Yes The base of the url.

setCrossOrigin

Set the crossorigin attribute

Argument Type Required Description
crossOrigin CrossOrigin Yes The crossorigin value.

setFiles

Set the list of files to download

Argument Type Required Description
files Array. Yes The array of files urls.

setMaxTextureLODSize

Set the max texture LOD size

Argument Type Required Description
maxTextureLODSize Number Yes The max texture LOD size.

setStepFinishedCallback

Argument Type Required Description
stepFinishedCallback Yes

setTexture

Set the vtkTexture object

Argument Type Required Description
texture vtkTexture Yes The vtkTexture object.

setWaitTimeBetweenDownloads

Set the delay between downloads

Argument Type Required Description
waitTimeBetweenDownloads Number Yes The delay between downloads.

setWaitTimeToStart

Set the delay before the start of download

Argument Type Required Description
waitTimeToStart Number Yes The delay before the start of download.

startDownloads

Start the download

Source

index.d.ts
import { vtkObject } from "vtk.js/Sources/interfaces";
import vtkTexture from "vtk.js/Sources/Rendering/Core/Texture";

declare type CrossOrigin = '' | 'anonymous' | 'use-credentials';

/**
*
*/
interface ITextureLODsDownloaderInitialValues {
baseUrl?: string;
crossOrigin?: CrossOrigin;
files?: string[];
maxTextureLODSize?: number;
texture?: vtkTexture;
stepFinishedCallback?: any;
waitTimeToStart?: number;
waitTimeBetweenDownloads?: number;
}


export interface vtkTextureLODsDownloader extends vtkObject {

/**
* Get the base of the url
*/
getBaseUrl(): string;

/**
* Get the crossorigin attribute
*/
getCrossOrigin(): CrossOrigin | null;

/**
* Get the list of files to download
*/
getFiles(): string[];

/**
* Get the max texture LOD size
*/
getMaxTextureLODSize(): number;

/**
*
*/
getStepFinishedCallback(): any;

/**
* Get the vtkTexture object
*/
getTexture(): vtkTexture;

/**
* Get the delay between downloads
*/
getWaitTimeBetweenDownloads(): number;

/**
* Get the delay before the start of download.
*/
getWaitTimeToStart(): number;

/**
* Set the base of the url
* @param {String} baseUrl The base of the url.
*/
setBaseUrl(baseUrl: string): boolean;

/**
* Set the crossorigin attribute
* @param {CrossOrigin} crossOrigin The crossorigin value.
*/
setCrossOrigin(crossOrigin: CrossOrigin): boolean;

/**
* Set the list of files to download
* @param {String[]} files The array of files urls.
*/
setFiles(files: string[]): boolean;

/**
* Set the max texture LOD size
* @param {Number} maxTextureLODSize The max texture LOD size.
*/
setMaxTextureLODSize(maxTextureLODSize: number): boolean;

/**
*
* @param stepFinishedCallback
*/
setStepFinishedCallback(stepFinishedCallback: any): boolean;

/**
* Set the vtkTexture object
* @param {vtkTexture} texture The vtkTexture object.
*/
setTexture(texture: vtkTexture): boolean;

/**
* Set the delay between downloads
* @param {Number} waitTimeBetweenDownloads The delay between downloads.
*/
setWaitTimeBetweenDownloads(waitTimeBetweenDownloads: number): boolean;

/**
* Set the delay before the start of download
* @param {Number} waitTimeToStart The delay before the start of download.
*/
setWaitTimeToStart(waitTimeToStart: number): boolean;

/**
* Start the download
*/
startDownloads(): void;
}

/**
* Method used to decorate a given object (publicAPI+model) with vtkTextureLODsDownloader characteristics.
*
* @param publicAPI object on which methods will be bounds (public)
* @param model object on which data structure will be bounds (protected)
* @param {ITextureLODsDownloaderInitialValues} [initialValues] (default: {})
*/
export function extend(publicAPI: object, model: object, initialValues?: ITextureLODsDownloaderInitialValues): void;

/**
* Method used to create a new instance of vtkTextureLODsDownloader
* @param {ITextureLODsDownloaderInitialValues} [initialValues] for pre-setting some of its content
*/
export function newInstance(initialValues?: ITextureLODsDownloaderInitialValues): vtkTextureLODsDownloader;

/**
* vtkTextureLODsDownloader provides a way to download textures by bulk.
*/
export declare const vtkTextureLODsDownloader: {
newInstance: typeof newInstance;
extend: typeof extend;
}
export default vtkTextureLODsDownloader;
index.js
import macro from 'vtk.js/Sources/macro';

const { vtkErrorMacro } = macro;

// ----------------------------------------------------------------------------

const getRemoteFileSize = (url) =>
// This function only works if the server provides a 'Content-Length'.
// For some reason, the 'Content-Length' header does not appear to be
// given for CORS HEAD requests on firefox. So this will not work on
// firefox if the images do not have the same origin as the html file.
// TODO: figure out how to make this work for CORS requests on firefox.
new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('HEAD', url, true);

xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
const size = xhr.getResponseHeader('Content-Length');
resolve(size);
} else {
console.log('Failed to get remote file size of', url);
reject(xhr);
}
}
};

xhr.send();
});

// ----------------------------------------------------------------------------
// vtkTextureLODsDownloader methods
// ----------------------------------------------------------------------------

function vtkTextureLODsDownloader(publicAPI, model) {
// Set our className
model.classHierarchy.push('vtkTextureLODsDownloader');

const internal = {
downloadStack: [],
};

//--------------------------------------------------------------------------

publicAPI.startDownloads = () => {
if (!model.texture) {
vtkErrorMacro('Texture was not set.');
return;
}

if (!model.files || model.files.length === 0) {
vtkErrorMacro('No files set.');
return;
}

let baseUrl = model.baseUrl;
if (baseUrl && !baseUrl.endsWith('/')) {
baseUrl += '/';
}

// Create the download stack
internal.downloadStack = [];
model.files.forEach((file) =>
internal.downloadStack.push(`${baseUrl}${file}`)
);

const downloadNextTexture = () => {
if (internal.downloadStack.length === 0) {
return;
}

// For later use
const asyncDownloadNextTexture = () => {
setTimeout(downloadNextTexture, model.waitTimeBetweenDownloads);
};

const img = new Image();
if (model.crossOrigin) {
img.crossOrigin = model.crossOrigin;
}

const url = internal.downloadStack.shift();
getRemoteFileSize(url)
.then((size) => {
if (!size || size / 1024 > model.maxTextureLODSize) {
if (!size) {
console.log('Failed to get image size');
} else {
console.log(
'Skipping image',
url,
', because it is larger',
'than the max texture size:',
model.maxTextureLODSize,
'KiB'
);
}
asyncDownloadNextTexture();
return;
}

img.src = url;
// Decode the image asynchronously in an attempt to prevent a
// freeze during rendering.
// In theory, this should help, but my profiling indicates that
// it does not help much... maybe it is running in the main
// thread anyways?
img
.decode()
.then(() => {
model.texture.setImage(img);
if (model.stepFinishedCallback) {
model.stepFinishedCallback();
}
asyncDownloadNextTexture();
})
.catch((encodingError) => {
console.log('Failed to decode image:', img.src);
console.log('Error is:', encodingError);
asyncDownloadNextTexture();
});
})
.catch((xhr) => {
console.log('Failed to get size of:', url);
console.log('status was:', xhr.status);
console.log('statusText was:', xhr.statusText);
asyncDownloadNextTexture();
});
};

setTimeout(downloadNextTexture, model.waitTimeToStart);
};
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

const DEFAULT_VALUES = {
baseUrl: '',
files: [],
texture: null,
crossOrigin: undefined,
// The max texture LOD file size in KiB
maxTextureLODSize: 50000,
stepFinishedCallback: null,
// These are in milliseconds
waitTimeToStart: 4000,
waitTimeBetweenDownloads: 0,
};

// ----------------------------------------------------------------------------

export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);

macro.obj(publicAPI, model);

// Create get-set macros
macro.setGet(publicAPI, model, [
'baseUrl',
'files',
'texture',
'crossOrigin',
'maxTextureLODSize',
'stepFinishedCallback',
'waitTimeToStart',
'waitTimeBetweenDownloads',
]);

// Object specific methods
vtkTextureLODsDownloader(publicAPI, model);
}

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(
extend,
'vtkTextureLODsDownloader'
);

// ----------------------------------------------------------------------------

export default { newInstance, extend };