Source: texture/textureArray.js

const THREE = require('three');

/**
 * Texture array object for holding array of images into
 * texures unit that can be used by other texture primitives.
 * 
 * @class
 * @author Alan Wu
 * @return {TextureArray}
 */
const TextureArray = function () {
  (require('./texture').Texture).call(this);
  this.isTextureArray = true;


  /**
   * Read images from an array containg src locations.
   * 
   * @async
   * @param {Array} srcArrays - List of source location of the images.
   */
  this.loadFromImages = async (srcArrays) => {
    let w = 1;
    let h = 1;
    let d = 0;
    if (srcArrays && srcArrays.length) {
      this.isLoading = true;
      const image = new Image();
      image.crossOrigin = "Anonymous";
      const canvas = document.createElement("canvas");
      let length = 0;
      const dataStacks = new Array(srcArrays.length);
      for (let i = 0; i < srcArrays.length; i++) {
        const data = await this.imageToUint8Array(this, image, srcArrays[i], canvas);
        if (data && data.array) {
          w = data.width;
          h = data.height;
          dataStacks[d] = data.array;
          length += dataStacks[d].length;
          d++;
        }
      }
      const fullArray = new Uint8Array(length);
      length = 0;
      dataStacks.forEach(data => {
        fullArray.set(data, length);
        length += data.length;
      });

      this.impl = new THREE.DataTexture2DArray(fullArray, w, h, d);
      this.size = {
        width: w,
        height: h,
        depth: d
      };
      this.isLoading = false;
      this.impl.needsUpdate = true;
    }
  }

  /**
   * Get and create the material containing shaders and the textures.
   * The texture must be read and ready before calling this function.
   * 
   *
   * @param {Object} options - Customise the material with the options object.
   * @param {String} options.fs - string of the fragment shader used for 
   * visualisation.
   * @param {String} options.vs - string of the vertex shader used for 
   * visualisation.
   * @param {Object} options.uniforms - Containing the data to be passed into the shaders.
   * @param {String} options.glslVersion - Version of glsl used for compile this shader.
   * 
   */
  this.getMaterial = (options) => {
    if (this.impl) {
      let material = undefined;
      if (options) {
        if (options.vs && options.fs) {
          let transparent = true;
          if (options.transparent)
            transparent = options.transparent;
          let side = THREE.FrontSide;
          if (options.side)
            side = options.side;
          material = new THREE.ShaderMaterial({
            transparent,
            uniforms: options.uniforms,
            vertexShader: options.vs,
            fragmentShader: options.fs,
            side
          });
          if (options.glslVersion) {
            material.glslVersion = options.glslVersion;
          }
        }
      } else {
        material = new THREE.MeshBasicMaterial({
          color: new THREE.Color(1, 1, 1),
          transparent: false,
          opacity: 1.0,
          map: this.impl,
          side: THREE.DoubleSide
        });
      }
      if (material) {
        material.needsUpdate = true;
        return material;
      }
    }
  }
}

TextureArray.prototype = Object.create((require('./texture').Texture).prototype);
exports.TextureArray = TextureArray;