Repository

js/Mobilizing/renderer/3D/three/texture/Texture.js

import * as THREE from 'three';

/**
* Texture are bitmap pictures loaded in the graphic card memory so they can be mapped on a geometry surface. Usually, texture are mapped through a Material. Keep in mind that WebGL, as an impletation of OpenGL, shares the same kind of limitations : textures sources should be power of 2 (even if here, Three.js is doing the job of resizing for you if they're not).
* Constants list for possible texture's mapping mode :
*
* Texture.UVMapping
* Texture.CubeReflectionMapping
* Texture.CubeRefractionMapping
* Texture.EquirectangularReflectionMapping
* Texture.EquirectangularRefractionMapping
* Texture.CubeUVReflectionMapping
*/

export default class Texture {
    /**
    * @param {Object} params Parameters object, given by the constructor.
    * @param {Context} params.image the Image object.
    * @param {String} params.canvas the canvas object.
    */
    constructor({
        image = undefined,
        canvas = undefined,
        cubeCamera = undefined,
    } = {}) {
        this.image = image;
        this.canvas = canvas;
        this.cubeCamera = cubeCamera;

        if (!this.cubeCamera) {
            this._texture = new THREE.Texture();
        }
        else {
            console.log(this.cubeCamera.getCubeRenderTarget().texture);
            this._texture = this.cubeCamera.getCubeRenderTarget().texture;
        }

        if (this.image) {
            this.fromImage(this.image);
        }
        else if (this.canvas) {
            this.fromCanvas(this.canvas);
        }
    }

    /**
    * @returns the Three.js native object used in this class
    */
    getNativeObject() {
        return this._texture;
    }

    /**
    * Create the texture from an image file
    * @param {Image} image tells if the loader should force the main process to wait for the end of
    */
    fromImage(image) {
        this._texture.image = image;
        this._texture.needsUpdate = true;

        this.width = image.width;
        this.height = image.height;
    }

    /**
    * Create the texture from a Canvas DOM element (can be Mobilizing itself -> when we'll can catch a WebGL canvas pixels...)
    * @param {canvas} canvas canvas
    */
    fromCanvas(canvas) {
        this._texture.image = canvas;
        this._texture.needsUpdate = true;

        this._texture.magFilter = THREE.LinearFilter;
        //this._texture.minFilter = THREE.LinearMipMapLinearFilter;
        this._texture.minFilter = THREE.LinearFilter;

        this.width = this._texture.image.width;
        this.height = this._texture.image.height;

        //custom events management, used internally to autamatically refresh texture after drawn
        if (canvas.events) {
            canvas.events.on("drawn", () => {
                this.setNeedsUpdate(true);
            });
        }
    }

    /**
    * Clears the underlying Three.js texture object
    */
    erase() {
        this._texture.dispose();
    }

    /**
    * Define the repetition factor of this texture. If the value is > 1, then the texture will be mapped twice on the surface and so on. NB: usage of this method automatically sets the wrapS and wrapT properties to RepeatWrapping
    *
    * @param {float} u the new u texture coordinate repetition to use
    * @param {float} v the new u texture coordinate repetition to use
    */
    setRepeat(u, v) {
        if (this._texture && this._texture !== undefined) {
            this._texture.repeat.set(u, v);
            this._texture.wrapS = THREE.RepeatWrapping;
            this._texture.wrapT = THREE.RepeatWrapping;
        }
    }

    /**
    * How much a single repetition of the texture is offset from the beginning, in each direction U and V. Typical range is 0.0 to 1.0.
    * @param {Numbe} val offset between 0.0 to 1.0
    */
    setOffset(val) {
        this._texture.offset = val;
    }

    //TODO : setter and getter for Three.js texture props mapping

    /**
    * Set this to true to trigger an update next time the texture is used. Particularly important for setting the wrap mode.
    * @param {Boolean} val
    */
    setNeedsUpdate() {
        this._texture.needsUpdate = true;
    }

    /**
    * False by default, which is the norm for PNG images. Set to true if the RGB values have been stored premultiplied by alpha.
    *
    * @param {Boolean} val
    */
    setPremultiplyAlpha(val) {
        this._texture.premultiplyAlpha = val;
    }

    /**
    * How the image is applied to the object. An object type of Texture.UVMapping is the default, where the U,V coordinates are used to apply the map.
    * @param {Number} mapping
    */
    setMapping(mapping) {
        this._texture.mapping = mapping;
    }
}

Texture.UVMapping = THREE.UVMapping;
Texture.CubeReflectionMapping = THREE.CubeReflectionMapping;
Texture.CubeRefractionMapping = THREE.CubeRefractionMapping;
Texture.EquirectangularReflectionMapping = THREE.EquirectangularReflectionMapping;
Texture.EquirectangularRefractionMapping = THREE.EquirectangularRefractionMapping;
Texture.CubeUVReflectionMapping = THREE.CubeUVReflectionMapping;