import { Matrix44 } from "./Matrix44" ; import { Quaternion } from "./Quaternion" ; import { ObjectPool } from "../core/ObjectPool" ; import { Matrix33 } from "./Matrix33" ; hidden export namespace Vector3Internal { export const xKey = "_x" ; export const yKey = "_y" ; export const zKey = "_z" ; export const wKey = "_w" ; } export class Vector3 { static zero = new Vector3 ( ) ; static one = new Vector3 ( 1.0 , 1.0 , 1.0 ) ; static right = new Vector3 ( 1 , 0 , 0 ) ; static up = new Vector3 ( 0 , 1 , 0 ) ; static forward = new Vector3 ( 0 , 0 , 1 ) ; hidden static dummy = new Vector3 ( ) ; hidden static dummy2 = new Vector3 ( ) ; static pool = new ObjectPool ( Vector3 , 128 ) ; get x ( ) { return this . _x ; } get y ( ) { return this . _y ; } get z ( ) { return this . _z ; } set x ( x ) { this . _x = x ; } set y ( y ) { this . _y = y ; } set z ( z ) { this . _z = z ; } get length ( ) { return Math . sqrt ( this . lengthSq ) ; } get lengthSq ( ) { return this . x * this . x + this . y * this . y + this . z * this . z ; } private _x : number ; private _y : number ; private _z : number ; private _array ! : number [ ] ; static distance ( a , b ) { return Math . sqrt ( Vector3 . distanceSq ( a , b ) ) ; } static distanceSq ( a , b ) { let dx = a . x - b . x ; let dy = a . y - b . y ; let dz = a . z - b . z ; return dx * dx + dy * dy + dz * dz ; } static fromPool ( ) { return Vector3 . pool . get ( ) ; } static fromArray ( a , index ? ) { let _index = index || 0 ; return new Vector3 ( a [ _index ] , a [ _index + 1 ] , a [ _index + 2 ] ) ; } constructor ( x ? , y ? , z ? ) { this . _x = x || 0 ; this . _y = y || 0 ; this . _z = z || 0 ; } flip ( ) { let { x , y , z } = this ; this . _x = - x ; this . _y = - y ; this . z = - z ; return this ; } cross ( v ) { return this . crossVectors ( this , v ) ; } crossVectors ( a , b ) { let ax = a . _x , ay = a . _y , az = a . _z ; let bx = b . _x , by = b . _y , bz = b . _z ; this . _x = ay * bz - az * by ; this . _y = az * bx - ax * bz ; this . z = ax * by - ay * bx ; return this ; } dot ( other ) { return ( this . _x * other . _x ) + ( this . _y * other . _y ) + ( this . _z * other . _z ) ; } substract ( other ) { return this . substractVectors ( this , other ) ; } substractVectors ( a , b ) { this . _x = a . _x - b . _x ; this . _y = a . _y - b . _y ; this . z = a . _z - b . _z ; return this ; } add ( other ) { return this . addVectors ( this , other ) ; } addVectors ( a , b ) { this . _x = a . _x + b . _x ; this . _y = a . _y + b . _y ; this . z = a . _z + b . _z ; return this ; } multiply ( scalar ) { this . _x *= scalar ; this . _y *= scalar ; this . z *= scalar ; return this ; } multiplyVector ( other ) { this . _x *= other . _x ; this . _y *= other . _y ; this . z *= other . _z ; return this ; } divide ( scalar ) { const inv = 1 / scalar ; this . _x *= inv ; this . _y *= inv ; this . z *= inv ; return this ; } divideVector ( other ) { this . _x /= other . _x ; this . _y /= other . _y ; this . z /= other . _z ; return this ; } min ( ) { return Math . min ( this . _x , this . _y , this . _z ) ; } max ( ) { return Math . max ( this . _x , this . _y , this . _z ) ; } normalize ( ) { const len = this . length ; if ( len === 0 ) { if ( process . env . NODE_ENV === "development" ) { console . assert ( false , "Normalizing a zero Vector3" ) ; } return this ; } else { return this . divide ( len ) ; } } lerp ( other , factor ) { return this . lerpVectors ( this , other , factor ) ; } lerpVectors ( v1 , v2 , factor ) { this . _x = v1 . _x + ( v2 . _x - v1 . _x ) * factor ; this . _y = v1 . _y + ( v2 . _y - v1 . _y ) * factor ; this . z = v1 . _z + ( v2 . _z - v1 . _z ) * factor ; return this ; } slerp ( other , factor ) { return this . slerpVectors ( this , other , factor ) ; } slerpVectors ( start , end , factor ) { let dot = start . dot ( end ) ; dot = Math . max ( Math . min ( dot , 1 ) , - 1 ) ; const theta = Math . acos ( dot ) * factor ; const relativeVec = Vector3 . dummy . copy ( start ) . multiply ( - dot ) . add ( end ) ; const length = relativeVec . length ; if ( length > 0 ) { relativeVec . multiply ( ( 1 / length ) ) . multiply ( Math . sin ( theta ) ) ; } return this . copy ( start ) . multiply ( Math . cos ( theta ) ) . add ( relativeVec ) ; } distFromSq ( other ) { const dx = this . _x - other . _x ; const dy = this . _y - other . _y ; const dz = this . _z - other . _z ; return dx * dx + dy * dy + dz * dz ; } distFrom ( other ) { return Math . sqrt ( this . distFromSq ( other ) ) ; } set ( x , y , z ) { this . _x = x ; this . _y = y ; this . z = z ; return this ; } setFromArray ( a , _offset ? ) { const offset = _offset || 0 ; console . assert ( a . length > offset + 2 ) ; this . _x = a [ offset ] ; this . _y = a [ offset + 1 ] ; this . z = a [ offset + 2 ] ; return this ; } setFromMatrix ( m ) { this . _x = m . data [ 12 ] ; this . _y = m . data [ 13 ] ; this . z = m . data [ 14 ] ; return this ; } setFromMatrixColumn ( m , index ) { return this . setFromArray ( m . data , index * 4 ) ; } rotate ( q ) { const { _x , _y , _z } = this ; const qx = q . x , qy = q . y , qz = q . z , qw = q . w ; const ix = qw * _x + qy * _z - qz * _y ; const iy = qw * _y + qz * _x - qx * _z ; const iz = qw * _z + qx * _y - qy * _x ; const iw = - qx * _x - qy * _y - qz * _z ; this . _x = ix * qw + iw * - qx + iy * - qz - iz * - qy ; this . _y = iy * qw + iw * - qy + iz * - qx - ix * - qz ; this . z = iz * qw + iw * - qz + ix * - qy - iy * - qx ; return this ; } transform ( m ) { const { _x , _y , _z } = this ; const e = m . data ; this . _x = e [ 0 ] * _x + e [ 4 ] * _y + e [ 8 ] * _z + e [ 12 ] ; this . _y = e [ 1 ] * _x + e [ 5 ] * _y + e [ 9 ] * _z + e [ 13 ] ; this . _z = e [ 2 ] * _x + e [ 6 ] * _y + e [ 10 ] * _z + e [ 14 ] ; const w = e [ 3 ] * _x + e [ 7 ] * _y + e [ 11 ] * _z + e [ 15 ] ; return this . multiply ( 1 / w ) ; } transformDirection ( m ) { const { _x , _y , _z } = this ; const e = m . data ; this . _x = e [ 0 ] * _x + e [ 4 ] * _y + e [ 8 ] * _z ; this . _y = e [ 1 ] * _x + e [ 5 ] * _y + e [ 9 ] * _z ; this . _z = e [ 2 ] * _x + e [ 6 ] * _y + e [ 10 ] * _z ; return this . normalize ( ) ; } transformMatrix33 ( m ) { const { _x , _y , _z } = this ; var e = m . data ; this . _x = e [ 0 ] * _x + e [ 3 ] * _y + e [ 6 ] * _z ; this . _y = e [ 1 ] * _x + e [ 4 ] * _y + e [ 7 ] * _z ; this . _z = e [ 2 ] * _x + e [ 5 ] * _y + e [ 8 ] * _z ; return this ; } copy ( other ) { this . _x = other . _x ; this . _y = other . _y ; this . z = other . _z ; return this ; } equals ( other ) { return this . _x === other . _x && this . _y === other . _y && this . _z === other . _z ; } asArray ( ) { if ( ! this . _array ) { this . _array = [ this . _x , this . _y , this . _z ] ; return this . _array ; } this . _array [ 0 ] = this . _x ; this . _array [ 1 ] = this . _y ; this . _array [ 2 ] = this . _z ; return this . _array ; } toArray ( a , offset ) { a [ offset ] = this . _x ; a [ offset + 1 ] = this . _y ; a [ offset + 2 ] = this . _z ; return a ; } projectOnLine ( a , b ) { const bMinusA = Vector3 . dummy ; const pointMinusA = Vector3 . dummy2 ; bMinusA . substractVectors ( b , a ) . normalize ( ) ; pointMinusA . substractVectors ( this , a ) ; return bMinusA . dot ( pointMinusA ) ; } projectOnVector ( a ) { const otherLength = a . length ; if ( otherLength < Number . EPSILON ) { return this ; } const aNormalized = Vector3 . dummy . copy ( a ) . multiply ( 1 / otherLength ) ; const scalarProjection = this . dot ( aNormalized ) ; return this . copy ( aNormalized ) . multiply ( scalarProjection ) ; } plus ( other ) { return Vector3 . dummy . copy ( this ) . add ( other ) ; } minus ( other ) { return Vector3 . dummy . copy ( this ) . substract ( other ) ; } reflect ( normal ) { Vector3 . dummy . copy ( normal ) . multiply ( 2 * this . dot ( normal ) ) ; this . substract ( Vector3 . dummy ) ; } }