Source: og/entity/BaseBillboard.js

/**
 * @module og/entity/BaseBillboard
 */

"use strict";

import * as utils from "../utils/shared.js";
import { Vec3 } from "../math/Vec3.js";
import { LOCK_FREE, LOCK_UPDATE } from "./LabelWorker.js";

/**
 * Base prototype for billboard and label classes.
 * @class
 * @param {Object} [options] - Options:
 * @param {Vec3|Array.<number>} [options.position] - Billboard spatial position.
 * @param {number} [options.rotation] - Screen angle rotaion.
 * @param {Vec4|string|Array.<number>} [options.color] - Billboard color.
 * @param {Vec3|Array.<number>} [options.alignedAxis] - Billboard aligned vector.
 * @param {Vec3|Array.<number>} [options.offset] - Billboard center screen offset.
 * @param {boolean} [options.visibility] - Visibility.
 */
class BaseBillboard {
    constructor(options) {
        options = options || {};

        /**
         * Object unic identifier.
         * @public
         * @readonly
         * @type {number}
         */
        this.id = BaseBillboard._staticCounter++;

        /**
         * Billboard center cartesian position.
         * @protected
         * @type {Vec3}
         */
        this._position = utils.createVector3(options.position);

        this._positionHigh = new Vec3();

        this._positionLow = new Vec3();

        Vec3.doubleToTwoFloats(this._position, this._positionHigh, this._positionLow);

        /**
         * Screen space rotation angle.
         * @protected
         * @type {number}
         */
        this._rotation = options.rotation || 0;

        /**
         * RGBA color.
         * @protected
         * @type {Vec4}
         */
        this._color = utils.createColorRGBA(options.color);

        /**
         * Cartesian aligned axis vector.
         * @protected
         * @type {Vec3}
         */
        this._alignedAxis = utils.createVector3(options.alignedAxis);

        /**
         * Billboard center screen space offset. Where x,y - screen space offset and z - depth offset.
         * @protected
         * @type {math.Vecto3}
         */
        this._offset = utils.createVector3(options.offset);

        /**
         * Billboard visibility.
         * @protected
         * @type {boolean}
         */
        this._visibility = options.visibility != undefined ? options.visibility : true;

        /**
         * Entity instance that holds this billboard.
         * @protected
         * @type {Entity}
         */
        this._entity = null;

        /**
         * Handler that stores and renders this billboard object.
         * @protected
         * @type {BillboardHandler}
         */
        this._handler = null;

        /**
         * Billboard handler array index.
         * @protected
         * @type {number}
         */
        this._handlerIndex = -1;

        /**
         * An indication that the object is ready to draw
         * @protected
         * @type {number}
         */
        this._isReady = false;

        this._lockId = LOCK_FREE;
    }

    static get _staticCounter() {
        if (!this._counter && this._counter !== 0) {
            this._counter = 0;
        }
        return this._counter;
    }

    static set _staticCounter(n) {
        this._counter = n;
    }

    /**
     * Sets billboard position.
     * @public
     * @param {number} x - X coordinate.
     * @param {number} y - Y coordinate.
     * @param {number} z - Z coordinate.
     */
    setPosition(x, y, z) {
        this._position.x = x;
        this._position.y = y;
        this._position.z = z;
        Vec3.doubleToTwoFloats(this._position, this._positionHigh, this._positionLow);
        if (this._isReady && this._handler) {
            this._handler.setPositionArr(this._handlerIndex, this._positionHigh, this._positionLow);
        } else if (this._lockId !== LOCK_FREE) {
            this._lockId = LOCK_UPDATE;
        }
    }

    /**
     * Sets billboard position.
     * @public
     * @param {Vec3} position - Cartesian coordinates.
     */
    setPosition3v(position) {
        this._position.x = position.x;
        this._position.y = position.y;
        this._position.z = position.z;
        Vec3.doubleToTwoFloats(position, this._positionHigh, this._positionLow);
        if (this._isReady && this._handler) {
            this._handler.setPositionArr(this._handlerIndex, this._positionHigh, this._positionLow);
        } else if (this._lockId !== LOCK_FREE) {
            this._lockId = LOCK_UPDATE;
        }
    }

    /**
     * Returns billboard position.
     * @public
     * @returns {Vec3}
     */
    getPosition() {
        return this._position;
    }

    /**
     * Sets screen space offset.
     * @public
     * @param {number} x - X offset.
     * @param {number} y - Y offset.
     * @param {number} [z] - Z offset.
     */
    setOffset(x, y, z) {
        this._offset.x = x;
        this._offset.y = y;
        z != undefined && (this._offset.z = z);
        if (this._isReady && this._handler) {
            this._handler.setOffsetArr(this._handlerIndex, this._offset);
        } else if (this._lockId !== LOCK_FREE) {
            this._lockId = LOCK_UPDATE;
        }
    }

    /**
     * Sets screen space offset.
     * @public
     * @param {Vec2} offset - Offset size.
     */
    setOffset3v(offset) {
        this.setOffset(offset.x, offset.y, offset.z);
    }

    /**
     * Returns billboard screen space offset size.
     * @public
     * @returns {Vec3}
     */
    getOffset() {
        return this._offset;
    }

    /**
     * Sets billboard screen space rotation in radians.
     * @public
     * @param {number} rotation - Screen space rotation in radians.
     */
    setRotation(rotation) {
        if (rotation !== this._rotation) {
            this._rotation = rotation;
            if (this._isReady && this._handler) {
                this._handler.setRotationArr(this._handlerIndex, rotation);
            } else if (this._lockId !== LOCK_FREE) {
                this._lockId = LOCK_UPDATE;
            }
        }
    }

    /**
     * Gets screen space rotation.
     * @public
     * @returns {number}
     */
    getRotation() {
        return this._rotation;
    }

    /**
     * Sets billboard opacity.
     * @public
     * @param {number} a - Billboard opacity.
     */
    setOpacity(a) {
        if (a !== this._color.w) {
            a != undefined && (this._color.w = a);
            if (this._isReady && this._handler) {
                this._handler.setRgbaArr(this._handlerIndex, this._color);
            } else if (this._lockId !== LOCK_FREE) {
                this._lockId = LOCK_UPDATE;
            }
        }
    }

    /**
     * Sets RGBA color. Each channel from 0.0 to 1.0.
     * @public
     * @param {number} r - Red.
     * @param {number} g - Green.
     * @param {number} b - Blue.
     * @param {number} a - Alpha.
     */
    setColor(r, g, b, a) {
        if (a !== this._color.w || r !== this._color.x || g !== this._color.y || this._color.z !== b) {
            this._color.x = r;
            this._color.y = g;
            this._color.z = b;
            a != undefined && (this._color.w = a);
            if (this._isReady && this._handler) {
                this._handler.setRgbaArr(this._handlerIndex, this._color);
            } else if (this._lockId !== LOCK_FREE) {
                this._lockId = LOCK_UPDATE;
            }
        }
    }

    /**
     * Sets RGBA color. Each channel from 0.0 to 1.0.
     * @public
     * @param {Vec4} color - RGBA vector.
     */
    setColor4v(color) {
        this.setColor(color.x, color.y, color.z, color.w);
    }

    /**
     * Sets billboard color.
     * @public
     * @param {string} color - HTML style color.
     */
    setColorHTML(color) {
        this.setColor4v(utils.htmlColorToRgba(color));
    }

    /**
     * Returns RGBA color.
     * @public
     * @returns {Vec4}
     */
    getColor() {
        return this._color;
    }

    /**
     * Sets billboard visibility.
     * @public
     * @param {boolean} visibility - Visibility flag.
     */
    setVisibility(visibility) {
        if (visibility !== this._visibility) {
            this._visibility = visibility;
            if (this._isReady && this._handler) {
                this._handler.setVisibility(this._handlerIndex, visibility);
            } else if (this._lockId !== LOCK_FREE) {
                this._lockId = LOCK_UPDATE;
            }
        }
    }

    /**
     * Returns billboard visibility.
     * @public
     * @returns {boolean}
     */
    getVisibility() {
        return this._visibility;
    }

    /**
     * Sets billboard cartesian aligned vector.
     * @public
     * @param {number} x - Aligned vector X coordinate.
     * @param {number} y - Aligned vector Y coordinate.
     * @param {number} z - Aligned vector Z coordinate.
     */
    setAlignedAxis(x, y, z) {
        this._alignedAxis.x = x;
        this._alignedAxis.y = y;
        this._alignedAxis.z = z;
        if (this._isReady && this._handler) {
            this._handler.setAlignedAxisArr(this._handlerIndex, this._alignedAxis);
        } else if (this._lockId !== LOCK_FREE) {
            this._lockId = LOCK_UPDATE;
        }
    }

    /**
     * Sets billboard aligned vector.
     * @public
     * @param {math.Vecto3} alignedAxis - Vector to align.
     */
    setAlignedAxis3v(alignedAxis) {
        this.setAlignedAxis(alignedAxis.x, alignedAxis.y, alignedAxis.z);
    }

    /**
     * Returns aligned vector.
     * @public
     * @returns {Vec3}
     */
    getAlignedAxis() {
        return this._alignedAxis;
    }

    /**
     * Removes billboard from hander.
     * @public
     */
    remove() {
        this._entity = null;
        this._handler && this._handler.remove(this);
    }

    /**
     * Sets billboard picking color.
     * @public
     * @param {Vec3} color - Picking color.
     */
    setPickingColor3v(color) {
        if (this._isReady && this._handler) {
            this._handler.setPickingColorArr(this._handlerIndex, color);
        } else if (this._lockId !== LOCK_FREE) {
            this._lockId = LOCK_UPDATE;
        }
    }
}

export { BaseBillboard };