import { EPSILON } from "../common"; export class vec3 { /** * @var */ public values = new Float32Array(3); public get x(): number { return this.values[0]; } public get y(): number { return this.values[1]; } public get z(): number { return this.values[2]; } public set x(value: number) { this.values[0] = value; } public set y(value: number) { this.values[1] = value; } public set z(value: number) { this.values[2] = value; } public constructor(values: number[] | null = null) { if (values !== null) { this.x = values[0]; this.y = values[1]; this.z = values[2]; } else { this.x = this.y = this.z = 0; } } public at(index: number): number { return this.values[index]; } public reset(x: number = 0, y: number = 0, z: number = 0): void { this.x = x; this.y = y; this.z = z; } public copy(dest: vec3 | null = null): vec3 { if (!dest) dest = new vec3(); dest.x = this.x; dest.y = this.y; dest.z = this.z; return dest; } /** * 取负向量 * @param dest * @returns */ public negate(dest: vec3 | null = null): vec3 { if (!dest) dest = this; dest.x = -this.x; dest.y = -this.y; dest.z = -this.z; return dest; } /** * 判断是否相等 * @param vector * @param threshold * @returns */ public equals(vector: vec3, threshold = EPSILON): boolean { if (Math.abs(this.x - vector.x) > threshold) return false; if (Math.abs(this.y - vector.y) > threshold) return false; if (Math.abs(this.z - vector.z) > threshold) return false; return true; } /** * 获取向量的模 */ public get length(): number { return Math.sqrt(this.length2); } /** * 向量模的平方 */ public get length2(): number { let x = this.x, y = this.y, z = this.z; return (x * x + y * y + z * z); } /** * 向量相加 * @param vector * @returns */ add(vector: vec3): vec3 { this.x += vector.x; this.y += vector.y; this.z += vector.z; return this; } /** * 向量相减 * @param vector * @returns */ subtract(vector: vec3): vec3 { this.x -= vector.x; this.y -= vector.y; this.z -= vector.z; return this; } /** * 向量缩放 * @param value * @param dest * @returns */ public scale(value: number, dest: vec3 | null = null): vec3 { if (!dest) { dest = this; } else { this.copy(dest); } dest.x *= value; dest.y *= value; dest.z *= value; return dest; } /** * 向量单位化 * @param dest * @returns */ public normalize(dest: vec3 | null = null): vec3 { if (!dest) { dest = this; } let length = this.length; if (length === 1) { return this; } if (length === 0) { dest.x = 0 dest.y = 0; dest.z = 0; return dest; } dest.x /= length; dest.y /= length; dest.z /= length; return dest; } /** * 向量单位化 * @returns */ public normalize2(): number { let length = this.length; this.x /= length; this.y /= length; this.z /= length; return length; } public print(): void { console.log("[ " + this.x + " " + this.y + " " + this.z +" ]"); } /** * 向量缩放 * @param vector * @param value * @param dest * @returns */ public static multiplyScalar(vector: vec3, value: number, dest: vec3 | null = null): vec3 { if (!dest) dest = new vec3(); dest.x *= value; dest.y *= value; dest.z *= value; return dest; } /** * 向量叉乘 * @param vector * @param vector2 * @param dest * @returns */ public static cross(vector: vec3, vector2: vec3, dest: vec3 | null = null): vec3 { if (!dest) dest = new vec3(); let x = vector.x, y = vector.y, z = vector.z; let x2 = vector2.x, y2 = vector2.y, z2 = vector2.z; dest.x = y * z2 - z * y2; dest.y = z * x2 - x * z2; dest.z = x * y2 - y * x2; return dest; } /** * 向量点乘 * @param vector * @param vector2 * @returns */ public static dot(vector: vec3, vector2: vec3): number { let x = vector.x, y = vector.y, z = vector.z; let x2 = vector2.x, y2 = vector2.y, z2 = vector2.z; return (x * x2 + y * y2 + z * z2); } public static sum(vector: vec3, vector2: vec3, dest: vec3 | null = null): vec3 { if (!dest) dest = new vec3(); dest.x = vector.x + vector2.x; dest.y = vector.y + vector2.y; dest.z = vector.z + vector2.z; return dest; } public static difference(vector: vec3, vector2: vec3, dest: vec3 | null = null): vec3 { if (!dest) dest = new vec3(); dest.x = vector.x - vector2.x; dest.y = vector.y - vector2.y; dest.z = vector.z - vector2.z; return dest; } static readonly up = new vec3([0, 1, 0]); static readonly down = new vec3([0, -1, 0]); static readonly right = new vec3([1, 0, 0]); static readonly left = new vec3([-1, 0, 0]); static readonly forward = new vec3([0, 0, 1]); static readonly backward = new vec3([0, 0, -1]); static readonly zero = new vec3([0, 0, 0]); static v0 = new vec3([0, 0, 0]); static v1 = new vec3([0, 0, 0]); static v2 = new vec3([0, 0, 0]); }