Repository

js/Mobilizing/renderer/3D/three/scene/Light.js

import * as THREE from "three";

import Color from "../types/Color";
import Vector3 from "../types/Vector3";
import Transform from "./Transform";

/**
* Light will enable object to be seen in space. Camera and Light are requiered for a basic scene.
*/
export default class Light {

    /**
    * @param {Object} params Parameters object, given by the constructor.
    * @param {String} [params.type="point"] one of "point", "directional", "ambient", "spot"
    * @param {Number} [params.intensity=1]
    * @param {Number} [params.distance=1000] distance is taken in account only for point lights
    * @param {Color} [params.color=Color.white]
    */
    constructor({
        type = "point",
        color = Color.white.clone(),
        intensity = 1,
        distance = 5000,
    } = {}) {
        this.type = type;
        this.color = color;
        this.intensity = intensity;
        this.distance = distance;

        switch (this.type) {
            case "point":
                this._light = new THREE.PointLight(this.color);
                this._light.distance = 1000;
                break;

            case "directional":
                this._light = new THREE.DirectionalLight(this.color);
                this._light.position.set(1, 1, 1).normalize();
                break;

            case "ambient":
                this._light = new THREE.AmbientLight(this.color);
                this._light.position.set(1, 1, 1).normalize();
                break;

            case "spot":
                this._light = new THREE.SpotLight(this.color);
                this.target = new THREE.Object3D();
                this._light.target = this.target;
                break;

            default:
                this._light = new THREE.PointLight(this.color);
                this.type = "point";
        }

        this._light.intensity = this.intensity;
        this._light.distance = this.distance;
        this._light.color = this.color;

        this.transform = new Transform(this);
    }

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

    /**
    * Sets the light's intensity
    * @param {Object} val
    */
    setIntensity(val) {
        this._light.intensity = val;
    }

    /**
    * Gets the light's intensity
    * @param {Object} val
    */
    getIntensity() {
        return this._light.intensity;
    }

    /**
    * Sets the light's distance factor
    * @param {Number} val
    */
    setDistance(val) {
        if (this.type === "point" || this.type === "spot") {
            this._light.distance = val;
        }
    }

    /**
    * Gets the light's distance factor
    * @return {Number} the light distance factor
    */
    getDistance() {
        return this._light.distance;
    }

    /**
    * setColor
    * @param {Color} color
    */
    setColor(color) {
        this.color = color;
        this._light.color = this.color;
    }

    /**
    * getColor
    * @return {Color} color
    */
    getColor() {
        return this.color;
    }

    /**
    * Maximum extent of the spotlight, in radians, from its direction. Should be no more than Math.PI/2. The default is Math.PI/3.
    * @param {Number} angle the spot angle
    */
    setAngle(val) {
        if (this.type === "spot") {
            this._light.angle = val;
        }
    }

    /**
    * getAngle
    * @return {Number} the angle
    */
    getAngle() {
        return this._light.angle;
    }

    /**
    * Position in space to where the spot light points
    * @param {Object} x
    * @param {Object} y
    * @param {Object} z
    */
    setTargetPosition(arg1, arg2, arg3) {
        if (this.type === "spot") {
            if (arg1 instanceof Vector3) {
                this.target.position.set(arg1.x, arg1.y, arg1.z);
                this.target.updateMatrixWorld();
            }
            else {
                this.target.position.set(arg1, arg2, arg3);
                this.target.updateMatrixWorld();
            }
        }
    }

    /**
    * Smoothness of the spot impact shape (makes the light circle blurry)
    * @param {Object} val between 0 and 1
    */
    setPenumbra(val) {
        this._light.penumbra = val;
    }

    /**
    * setCastShadow
    * @param {Boolean} enabled
    */
    setCastShadow(enabled) {
        this._light.castShadow = enabled;
    }

    /**
    * set the Shadow map Size
    * @param {Number} width
    * @param {Number} height
    */
    setShadowSize(width, height) {
        this._light.shadow.mapSize.width = width; //shadow map size
        this._light.shadow.mapSize.height = height; //shadow map size
    }

    /**
    * setShadowDistance
    * @param {Number} near min shadow distance
    * @param {Number} far max shadow distance
    */
    setShadowDistance(near, far) {
        this._light.shadow.camera.near = near; //min shadow distance
        this._light.shadow.camera.far = far; //max shadow distance
    }

    /**
    * @param {Boolean} value true or false to enable this light or not
    */
    setVisible(val) {
        this._light.visible = val;
    }

    /**
    * @return {Boolean} value true or false
    */
    getVisible() {
        return this._light.visible;
    }
}