import * as utils from "../utils/shared";
import {Entity} from "./Entity";
import {Quat, Vec3, Vec4} from "../math/index";
import {GeoObjectHandler} from "./GeoObjectHandler";
import {InstanceData} from "./InstanceData";
import type {NumberArray3} from "../math/Vec3";
import type {NumberArray4} from "../math/Vec4";
import {Object3d} from "../Object3d";
export const LOCAL_FORWARD = new Vec3(0.0, 0.0, -1.0);
/**
* Interface for GeoObject parameters.
* @typedef {Object} IGeoObjectParams
* @property {Object3d} [object3d] - 3D object associated with the geo object.
* @property {string} [objSrc] - Source url of the 3D object.
* @property {string} [tag] - Unique instancing drawing identifier tag.
* @property {Vec3 | NumberArray3} [position] - Position in Cartesian coordinates.
* @property {number | Vec3 | NumberArray3} [scale] - Scale of the object.
* @property {Vec3 | NumberArray3} [translate] - Translation offset.
* @property {Vec4 | NumberArray4 | string} [color] - RGBA color or HTML color string.
* @property {boolean} [visibility] - Visibility flag.
*/
export interface IGeoObjectParams {
object3d?: Object3d;
objSrc?: string;
tag?: string;
position?: Vec3 | NumberArray3;
scale?: number | Vec3 | NumberArray3;
translate?: Vec3 | NumberArray3;
color?: Vec4 | NumberArray4 | string;
visibility?: boolean;
}
/**
* Represents 3D object on the the globe or 3d space
* @class
* @param {IGeoObjectParams} options - Geo object parameters:
* @param {Object3d} [options.object3d] - 3D object associated with the geo object.
* @param {string} [options.objSrc] - Source url of the 3D object.
* @param {string} [options.tag] - Unique instancing drawing identifier tag.
* @param {Vec3 | NumberArray3} [options.position] - Position in Cartesian coordinates.
* @param {number | Vec3 | NumberArray3} [options.scale=1] - Scale of the object.
* @param {Vec3 | NumberArray3} [options.translate] - Translation offset.
* @param {Vec4 | NumberArray4 | string} [options.color] - RGBA color or HTML color string.
* @param {boolean} [options.visibility=true] - Visibility flag.
*
* @todo: GeoObject and GeoObjectHandler provides instanced objects only.
* It would be nice if it could provide not instanced rendering loop too.
*/
class GeoObject {
protected _tag: string;
static __counter__: number = 0;
/**
* Entity instance that holds this geo object.
* @public
* @type {Entity}
*/
public _entity: Entity | null;
/**
* Geo object center cartesian position.
* @protected
* @type {Vec3}
*/
protected _position: Vec3;
public _rtcPositionHigh: Vec3;
public _rtcPositionLow: Vec3;
protected _scale: Vec3;
protected _translate: Vec3;
protected _localPosition: Vec3;
/**
* RGBA color.
* @public
* @type {Vec4}
*/
public _color: Vec4;
protected _qFrame: Quat;
public _qRot: Quat;
protected _direction: Vec3;
public _handler: GeoObjectHandler | null;
public _handlerIndex = -1;
public _tagData: InstanceData | null;
public _tagDataIndex: number;
protected _object3d: Object3d;
public _objectSrc?: string;
protected _visibility: boolean;
protected _children: GeoObject[];
constructor(options: IGeoObjectParams) {
this._tag = options.tag || `tag_${GeoObject.__counter__++}`;
this._entity = null;
this._position = utils.createVector3(options.position);
this._rtcPositionHigh = new Vec3();
this._rtcPositionLow = new Vec3();
this._scale = utils.createVector3(options.scale, new Vec3(1, 1, 1));
this._translate = utils.createVector3(options.translate, new Vec3());
this._localPosition = new Vec3();
this._color = utils.createColorRGBA(options.color, new Vec4(0.15, 0.15, 0.15, 1.0));
this._handler = null;
this._handlerIndex = -1;
this._tagData = null;
this._tagDataIndex = -1;
let object3d = options.object3d;
if ((!options.object3d || options.object3d?.vertices.length === 0)) {
object3d = new Object3d();
}
if (options.objSrc) {
this.setObjectSrc(options.objSrc)
this._objectSrc = options.objSrc;
}
this._object3d = object3d as Object3d;
// if (options.colorTexture) {
// this.setColorTexture(options.colorTexture)
// }
this._visibility = (options.visibility != undefined ? options.visibility : true);
this._children = [];
this._direction = new Vec3();
this._qFrame = new Quat();
this._qRot = Quat.IDENTITY;
}
/**
* Gets the unique tag of the geo object.
* @returns {string}
*/
public get tag() {
return this._tag;
}
/**
* Gets the position of the geo object.
* @public
* @returns {Vec3}
*/
public getPosition(): Vec3 {
return this._position;
}
/**
* Gets the 3D object associated with this geo object.
* @public
* @returns {Object3d}
*/
public get object3d(): Object3d {
return this._object3d;
}
/**
* Gets geometry mesh vertices.
* @public
* @returns {number[]}
*/
public get vertices(): number[] {
return this._object3d.vertices;
}
/**
* Gets geometry mesh normals.
* @public
* @returns {number[]}
*/
public get normals(): number[] {
return this._object3d.normals;
}
/**
* Gets geometry mesh texture coordinates.
* @public
* @returns {number[]}
*/
public get texCoords(): number[] {
return this._object3d.texCoords;
}
/**
* Gets geometry mesh indices.
* @public
* @returns {number[]}
*/
public get indices(): number[] {
return this._object3d.indices;
}
/**
* Sets the opacity of the geo object.
* @param {number} a - Opacity value (0 to 1).
*/
public setOpacity(a: number) {
this._color.w = a;
this.setColor(this._color.x, this._color.y, this._color.z, a);
}
/**
* Gets the opacity of the geo object.
* @returns {number}
*/
public getOpacity(): number {
return this._color.w;
}
/**
* Sets the color of the geo object.
* @param {number} r - Red component.
* @param {number} g - Green component.
* @param {number} b - Blue component.
* @param {number} [a] - Alpha component.
*/
public setColor(r: number, g: number, b: number, a?: number) {
this._color.x = r;
this._color.y = g;
this._color.z = b;
a != undefined && (this._color.w = a);
this._handler && this._handler.setRgbaArr(this._tagData!, this._tagDataIndex, this._color);
}
/**
* Sets color.
* @public
* @param {Vec3 | Vec4} color - RGBA vector.
*/
public setColor4v(color: Vec3 | Vec4) {
this._color.x = color.x;
this._color.y = color.y;
this._color.z = color.z;
(color as Vec4).w != undefined && (this._color.w = (color as Vec4).w);
this._handler && this._handler.setRgbaArr(this._tagData!, this._tagDataIndex, this._color);
}
/**
* Sets geo object visibility.
* @public
* @param {boolean} visibility - Visibility flag.
*/
public setVisibility(visibility: boolean) {
this._visibility = visibility;
this._handler && this._handler.setVisibility(this._tagData!, this._tagDataIndex, visibility);
}
/**
* Returns geo object visibility.
* @public
* @returns {boolean}
*/
public getVisibility(): boolean {
return this._visibility;
}
/**
* Sets geo object position.
* @public
* @param {number} x - X coordinate.
* @param {number} y - Y coordinate.
* @param {number} z - Z coordinate.
*/
public setPosition(x: number, y: number, z: number) {
this._position.x = x;
this._position.y = y;
this._position.z = z;
this.updateRTCPosition();
this.updateRotation();
}
public updateRTCPosition() {
//Vec3.doubleToTwoFloats(this._position, this._rtcPositionHigh, this._rtcPositionLow);
if (this._handler) {
this._handler.getRTCPosition(this._position, this._rtcPositionHigh, this._rtcPositionLow);
this._handler.setRTCPositionArr(this._tagData!, this._tagDataIndex, this._rtcPositionHigh, this._rtcPositionLow);
}
}
/**
* Sets geo object position.
* @public
* @param {Vec3} position - Cartesian coordinates.
*/
public setPosition3v(position: Vec3) {
this.setPosition(position.x, position.y, position.z);
}
/**
* Sets Object3d for the object
* @param {Object3d} object
*/
public setObject(object: Object3d) {
this._object3d = object;
}
/**
* Sets the object url source.
* @param {string} src
*/
public setObjectSrc(src: string) {
this._objectSrc = src;
this._handler && this._handler.setObjectSrc(src, this.tag);
}
/**
* Sets object HTML color.
* @param {string} color
*/
public setColorHTML(color: string) {
this.setColor4v(utils.htmlColorToRgba(color));
}
/**
* Sets scales.
* @public
* @param {number} scale
*/
public setScale(scale: number) {
this._scale.x = this._scale.y = this._scale.z = scale;
this._handler && this._handler.setScaleArr(this._tagData!, this._tagDataIndex, this._scale);
}
/**
* Sets X, Y, Z axis scales
* @public
* @param {Vec3} scale
*/
public setScale3v(scale: Vec3) {
this._scale.copy(scale);
this._handler && this._handler.setScaleArr(this._tagData!, this._tagDataIndex, scale);
}
/**
* Gets scale.
* @publci
* @returns {Vec3}
*/
public getScale(): Vec3 {
return this._scale;
}
public setTranslate3v(translate: Vec3) {
this._translate.copy(translate);
this._handler && this._handler.setTranslateArr(this._tagData!, this._tagDataIndex, translate);
}
public getTranslate(): Vec3 {
return this._translate.clone();
}
/**
* Sets local offset position.
* @param {Vec3} localPosition
*/
public setLocalPosition3v(localPosition: Vec3) {
this._localPosition.copy(localPosition);
this._handler && this._handler.setLocalPositionArr(this._tagData!, this._tagDataIndex, localPosition);
}
/**
* Gets local offset position.
* @public
* @returns {Vec3}
*/
public getLocalPosition(): Vec3 {
return this._localPosition.clone();
}
/**
* Removes the geo object from the handler.
* @public
*/
public remove() {
this._entity = null;
this._handler && this._handler.remove(this);
}
/**
* Sets billboard picking color.
* @public
* @param {Vec3} color - Picking color.
*/
public setPickingColor3v(color: Vec3) {
this._handler && this._handler.setPickingColorArr(this._tagData!, this._tagDataIndex, color);
}
/**
* Sets the rotation quaternion.
* @public
* @param {Quat} qRot - Rotation quaternion.
*/
public setRotation(qRot: Quat) {
this._qRot.copy(qRot);
this._qRot.mulVec3Res(LOCAL_FORWARD, this._direction).normalize();
this.updateRotation();
}
/**
* Returns orientation quaternion.
* @public
* @returns {Quat}
*/
public getRotation(): Quat {
return this._qRot;
}
/**
* Update object rotation
*/
public updateRotation() {
this._handler && this._handler.setQRotArr(this._tagData!, this._tagDataIndex, this._qRot);
}
/**
* Returns object direction
* @publcu
* @returns {Vec3}
*/
public getDirection(): Vec3 {
return this._direction.clone();
}
}
export {GeoObject};