js/base/Vector4.js
- 'use strict'
-
- /**
- * Vector4 class
- * @access public
- */
- export default class Vector4 {
- /**
- * constructor
- * @access public
- * @param {float} x -
- * @param {float} y -
- * @param {float} z -
- * @param {float} w -
- * @constructor
- */
- constructor(x = 0.0, y = 0.0, z = 0.0, w = 0.0) {
- this.setValue(x, y, z, w)
- }
-
- clone() {
- return new Vector4(this.x, this.y, this.z, this.w)
- }
-
- setValue(x, y = 0.0, z = 0.0, w = 0.0) {
- if((x instanceof Vector4) || (x instanceof Object && x.w !== null)){
- this.x = x.x
- this.y = x.y
- this.z = x.z
- this.w = x.w
- }else{
- this.x = x || 0.0
- this.y = y || 0.0
- this.z = z || 0.0
- this.w = w || 0.0
- }
- }
-
- lerp(src1, src2, rate) {
- this.x = src1.x + rate * (src2.x - src1.x)
- this.y = src1.y + rate * (src2.y - src1.y)
- this.z = src1.z + rate * (src2.z - src1.z)
- this.w = src1.w + rate * (src2.w - src1.w)
- }
-
- slerp(src1, src2, rate) {
- const qr = src1.x * src2.x + src1.y * src2.y + src1.z * src2.z + src1.w * src2.w
-
- if(qr < 0){
- this.x = src1.x - (src1.x + src2.x) * rate
- this.y = src1.y - (src1.y + src2.y) * rate
- this.z = src1.z - (src1.z + src2.z) * rate
- this.w = src1.w - (src1.w + src2.w) * rate
- }else{
- this.x = src1.x + (src2.x - src1.x) * rate
- this.y = src1.y + (src2.y - src1.y) * rate
- this.z = src1.z + (src2.z - src1.z) * rate
- this.w = src1.w + (src2.w - src1.w) * rate
- }
- this.normalize()
- }
-
- ln(src) {
- const v = new Vector4()
- v.normalize(src)
-
- const n = Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
- if(n === 0){
- this.x = 0
- this.y = 0
- this.z = 0
- this.w = 0
- return
- }
- const theta = Math.atan2(n, v.w) / n
-
- this.x = theta * v.x
- this.y = theta * v.y
- this.z = theta * v.z
- this.w = 0
- }
-
- exp(src) {
- const n = Math.sqrt(src.x * src.x + src.y * src.y + src.z * src.z)
-
- if(n > 0.0){
- const sinn = Math.sin(n)
- this.x = sinn * src.x / n
- this.y = sinn * src.y / n
- this.z = sinn * src.z / n
- this.w = Math.cos(n)
- }else{
- this.x = 0.0
- this.y = 0.0
- this.z = 0.0
- this.w = 1.0
- }
- }
-
- normalize(src = this) {
- const square = 1.0 / Math.sqrt(src.x * src.x + src.y * src.y + src.z * src.z + src.w * src.w)
-
- this.x = src.x * square
- this.y = src.y * square
- this.z = src.z * square
- this.w = src.w * square
- }
-
- createAxis(axis, rotAngle) {
- if(Math.abs(rotAngle) < 0.0001){
- this.x = 0.0
- this.y = 0.0
- this.z = 0.0
- this.w = 1.0
- }else{
- const angle = rotAngle * 0.5
- const temp = Math.sin(angle)
-
- this.x = axis.x * temp
- this.y = axis.y * temp
- this.z = axis.z * temp
- this.w = Math.cos(angle)
- }
- }
-
- cross(src1, src2) {
- const x = src1.w * src2.x + src1.x * src2.w + src1.y * src2.z - src1.z * src2.y
- const y = src1.w * src2.y - src1.x * src2.z + src1.y * src2.w + src1.z * src2.x
- const z = src1.w * src2.z + src1.x * src2.y - src1.y * src2.x + src1.z * src2.w
- const w = src1.w * src2.w - src1.x * src2.x - src1.y * src2.y - src1.z * src2.z
-
- this.x = x
- this.y = y
- this.z = z
- this.w = w
- }
-
- eulerToQuaternion(eulerAngle) {
- const xRadian = eulerAngle.x * 0.5
- const yRadian = eulerAngle.y * 0.5
- const zRadian = eulerAngle.z * 0.5
- const sinX = Math.sin(xRadian)
- const cosX = Math.cos(xRadian)
- const sinY = Math.sin(yRadian)
- const cosY = Math.cos(yRadian)
- const sinZ = Math.sin(zRadian)
- const cosZ = Math.cos(zRadian)
-
- this.x = sinX * cosY * cosZ - cosX * sinY * sinZ
- this.y = cosX * sinY * cosZ + sinX * cosY * sinZ
- this.z = cosX * cosY * sinZ - sinX * sinY * cosZ
- this.w = cosX * cosY * cosZ + sinX * sinY * sinZ
- }
-
- transform(vec, matrix){
- const rx = vec.x * matrix.m11 + vec.y * matrix.m21 + vec.z * matrix.m31 + vec.w * matrix.m41
- const ry = vec.x * matrix.m12 + vec.y * matrix.m22 + vec.z * matrix.m32 + vec.w * matrix.m42
- const rz = vec.x * matrix.m13 + vec.y * matrix.m23 + vec.z * matrix.m33 + vec.w * matrix.m43
- const rw = vec.x * matrix.m14 + vec.y * matrix.m24 + vec.z * matrix.m34 + vec.w * matrix.m44
-
- this.x = rx
- this.y = ry
- this.z = rz
- this.w = rw
- }
-
- quaternionFromMatrix(mat) {
- const mx = mat.m11 - mat.m22 - mat.m33
- const my = mat.m22 - mat.m11 - mat.m33
- const mz = mat.m33 - mat.m11 - mat.m22
- const mw = mat.m11 + mat.m22 + mat.m33
-
- let biggestIndex = 0
- let mval = mw
- if(mx > mval) {
- mval = mx
- biggestIndex = 1
- }
- if(my > mval) {
- mval = my
- biggestIndex = 2
- }
- if(mz > mval) {
- mval = mz
- biggestIndex = 3
- }
-
- const biggestVal = Math.sqrt(mval + 1.0) * 0.5
- const mult = 0.25 / biggestVal
-
- switch(biggestIndex) {
- case 0:
- this.x = (mat.m23 - mat.m32) * mult
- this.y = (mat.m31 - mat.m13) * mult
- this.z = (mat.m12 - mat.m21) * mult
- this.w = biggestVal
- break
- case 1:
- this.x = biggestVal
- this.y = (mat.m12 + mat.m21) * mult
- this.z = (mat.m31 + mat.m13) * mult
- this.w = (mat.m23 - mat.m32) * mult
- break
- case 2:
- this.x = (mat.m12 + mat.m21) * mult
- this.y = biggestVal
- this.z = (mat.m23 + mat.m32) * mult
- this.w = (mat.m31 - mat.m13) * mult
- break
- case 3:
- this.x = (mat.m31 * mat.m13) * mult
- this.y = (mat.m23 * mat.m32) * mult
- this.z = biggestVal
- this.w = (mat.m12 - mat.m21) * mult
- break
- default:
- break
- }
- }
-
- getWebGLFloatArray() {
- return new Float32Array([
- this.x, this.y, this.z, this.w
- ])
- }
- }
-