UNPKG

@pilotlab/lux-attributes

Version:

A luxurious user experience framework, developed by your friends at Pilot.

332 lines (242 loc) 10.8 kB
import { IAttribute, AttributeChangeOptions } from '@pilotlab/lux-attributes'; import { List } from '@pilotlab/lux-collections'; import Types from './types'; import PointBase from './pointBase'; import Point from './point'; import IVector from './interfaces/iVector'; import { AttributeChangeActions, AttributeCreateOptions, DataType, IAttributeChangeOptions, IAttributeUpdateTracker } from '@pilotlab/lux-attributes'; import { IAnimationEaseFunction, ISpeed } from '@pilotlab/lux-animation'; /** * A Vector can represent point in 3D space, or a direction and length in 3D space. * The length (or magnitude) will always be the Euclidean distance (straight-line distance) * from (0, 0, 0) to (x, y, z) and the direction is also measured from (0, 0, 0) towards (x, y, z). */ export class Vector extends PointBase<Vector> implements IVector { constructor(x:number = 0, y:number = 0, z:number = 0, w:number = 0, label?:string) { super('vector', x, y, z, label); this.p_w = this.children.get('w', new AttributeCreateOptions(w, DataType.NUMBER, null, AttributeChangeOptions.zero)); } get w():number { return this.p_w.value; } set w(value:number) { this.p_w.set(value, AttributeChangeOptions.save.durationZero); } protected p_w:IAttribute; get size():number { return Math.sqrt(this.dot(this)); } get magnitude():number { return this.size; } get abs():Vector { return new Vector(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z), Math.abs(this.w)); } /*====================================================================* START: Public Methods *====================================================================*/ // out():Vector { return new Vector(this.x + this.coordinateSystem.x, this.coordinateSystem.y - this.y, this.z + this.coordinateSystem.z, this.w); } // // // outFloat32Array():Float32Array { // let ar:Float32Array = new Float32Array(this.children.list.size); // // for (let i:number = 0; i < this.children.list.size; i++) { // if (i < 3) ar[i] = this.children.list.item(i).value + this.coordinateSystem.children.list.item(i).value; // else ar[i] = this.children.list.item(i).value; // } // // return ar; // } /** * Get the scalar product of two Vectors */ dot(v:Vector):number { let values:List<IAttribute> = this.children.list; let valuesIn:List<IAttribute> = v.children.list; if (values.size != values.size) throw new Error('Vectors of different dimensions.'); let erg:number = 0.0; for (let i:number = 0; i < values.size; i++) erg += values.item(i).value * valuesIn.item(i).value; return erg; } /** * Returns the normalized version of the Vector. */ normalize():Vector { let m:number = this.magnitude; let values:List<IAttribute> = this.children.list; if (m <= Types.tolerance) m = 1.0; for (let i:number = 0; i < values.size; i++) { values.item(i).value = values.item(i).value / m; if (Math.abs(values.item(i).value) < Types.tolerance) values.item(i).value = 0.0; } return this; } multiply(v:Vector):Vector { let values:List<IAttribute> = this.children.list; let valuesIn:List<IAttribute> = v.children.list; if (valuesIn.size !== values.size) return null; for (let i:number = 0; i < values.size; i++) { values.item(i).value = values.item(i).value * valuesIn.item(i).value; } return this; } divide(v:Vector):Vector { let values:List<IAttribute> = this.children.list; let valuesIn:List<IAttribute> = v.children.list; if (valuesIn.size !== values.size) return null; for (let i:number = 0; i < values.size; i++) { values.item(i).value = values.item(i).value / valuesIn.item(i).value; } return this; } /*multiplyByMat3(matrix: mat3, dest: vec3 = null): vec3 { if (!dest) dest = this; return matrix.multiplyVec3(this, dest); } multiplyByQuat(quat: quat, dest: vec3 = null): vec3 { if (!dest) dest = this; return quat.multiplyVec3(this, dest); }*/ go( target:IVector, durationSpeed?:(number | ISpeed), ease?:IAnimationEaseFunction, repeatCount:number = 0 ):IAttributeUpdateTracker { const options:IAttributeChangeOptions = new AttributeChangeOptions(AttributeChangeActions.SIGNAL_CHANGE, durationSpeed, ease); options.repeatCount = repeatCount; return this.attributes.update(target, options); } /*====================================================================* START: Static Methods *====================================================================*/ static get identity():Vector { return new Vector(0, 0); } static fromPoint3D(pt:Point):Vector { return new Vector(pt.x, pt.y, pt.z, null); } static get empty():Vector { return new Vector(); } static cross(v1:Vector, v2:Vector, dest:Vector = null):Vector { let values1:List<IAttribute> = v1.children.list; let values2:List<IAttribute> = v2.children.list; if (values1.size != values2.size || values1.size < 3) return new Vector(); if (!dest) dest = new Vector(0, 0, 0); dest.x = v1.y * v2.z - v1.z * v2.y; dest.y = v1.z * v2.x - v1.x * v2.z; dest.z = v1.x * v2.y - v1.y * v2.x; return dest; } static dot(v1:Vector, v2:Vector):number { let values1:List<IAttribute> = v1.children.list; let values2:List<IAttribute> = v2.children.list; if (values1.size !== values2.size) return -1.0; let e:number = 0.0; let d:number = 0.0; for (let i:number = 0; i < values1.size; i++) { d = (values1.item(i).value * values2.item(i).value); e += d; } return e; } static distance(v1:Vector, v2:Vector):number { let values1:List<IAttribute> = v1.children.list; let values2:List<IAttribute> = v2.children.list; if (values1.size !== values2.size) return -1.0; let e:number = 0.0; let d:number = 0.0; for (let i:number = 0; i < values1.size; i++) { d = (values1.item(i).value - values2.item(i).value); e += d * d; } return Math.sqrt(e); } static direction(v1:Vector, v2:Vector, dest:Vector = new Vector()):Vector { let values1:List<IAttribute> = v1.children.list; let values2:List<IAttribute> = v2.children.list; let valuesDest:List<IAttribute> = dest.children.list; if (values1.size !== values2.size) return new Vector(); let d:number = 0.0; let size:number = 0.0; for (let i:number = 0; i < values1.size; i++) { valuesDest.item(i).value = values1.item(i).value - values2.item(i).value; size += d * d; } if (size === 0) { for (let i:number = 0; i < values1.size; i++) { valuesDest.item(i).value = 0; } return dest; } size = 1 / size; for (let i:number = 0; i < values1.size; i++) { valuesDest.item(i).value = valuesDest.item(i).value * size; } return dest; } static mix(v1:Vector, v2:Vector, time:number, dest:Vector = new Vector()):Vector { let values1:List<IAttribute> = v1.children.list; let values2:List<IAttribute> = v2.children.list; let valuesDest:List<IAttribute> = dest.children.list; if (values1.size !== values2.size) return new Vector(); for (let i:number = 0; i < values1.size; i++) { valuesDest.item(i).value = values1.item(i).value + time * (values2.item(i).value - values1.item(i).value); } return dest; } static sum(v1:Vector, v2:Vector, dest:Vector = new Vector()):Vector { let values1:List<IAttribute> = v1.children.list; let values2:List<IAttribute> = v2.children.list; let valuesDest:List<IAttribute> = dest.children.list; if (values1.size !== values2.size) return new Vector(); for (let i:number = 0; i < values1.size; i++) { valuesDest.item(i).value = values1.item(i).value + values2.item(i).value; } return dest; } static difference(v1:Vector, v2:Vector, dest:Vector = new Vector()):Vector { let values1:List<IAttribute> = v1.children.list; let values2:List<IAttribute> = v2.children.list; let valuesDest:List<IAttribute> = dest.children.list; if (values1.size !== values2.size) return new Vector(); for (let i:number = 0; i < values1.size; i++) { valuesDest.item(i).value = values1.item(i).value - values2.item(i).value; } return dest; } static product(v1:Vector, v2:Vector, dest:Vector = new Vector()):Vector { let values1:List<IAttribute> = v1.children.list; let values2:List<IAttribute> = v2.children.list; let valuesDest:List<IAttribute> = dest.children.list; if (values1.size !== values2.size) return new Vector(); for (let i:number = 0; i < values1.size; i++) { valuesDest.item(i).value = values1.item(i).value * values2.item(i).value; } return dest; } static quotient(v1:Vector, v2:Vector, dest:Vector = new Vector()):Vector { let values1:List<IAttribute> = v1.children.list; let values2:List<IAttribute> = v2.children.list; let valuesDest:List<IAttribute> = dest.children.list; if (values1.size !== values2.size) return new Vector(); for (let i:number = 0; i < values1.size; i++) { valuesDest.item(i).value = values1.item(i).value / values2.item(i).value; } return dest; } /*toQuat(dest: quat = null): quat { if (!dest) dest = new quat(); let c = new vec3(); let s = new vec3(); c.x = Math.cos(this.x * 0.5); s.x = Math.sin(this.x * 0.5); c.y = Math.cos(this.y * 0.5); s.y = Math.sin(this.y * 0.5); c.z = Math.cos(this.z * 0.5); s.z = Math.sin(this.z * 0.5); dest.x = s.x * c.y * c.z - c.x * s.y * s.z; dest.y = c.x * s.y * c.z + s.x * c.y * s.z; dest.z = c.x * c.y * s.z - s.x * s.y * c.z; dest.w = c.x * c.y * c.z + s.x * s.y * s.z; return dest; }*/ static zero = new Vector(0, 0, 0); static up = new Vector(0, 1, 0); static right = new Vector(1, 0, 0); static forward = new Vector(0, 0, 1); } // End class export default Vector;