UNPKG

@egjs/view360

Version:

360 integrated viewing solution from inside-out view to outside-in view. It provides user-friendly service by rotating 360 degrees through various user interaction such as motion sensor and touch.

376 lines (289 loc) 8.28 kB
/* eslint-disable */ /* * Copyright 2016 Google Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { window as win } from "../../../../utils/browser"; const MathUtil = win.MathUtil || {}; MathUtil.degToRad = Math.PI / 180; MathUtil.radToDeg = 180 / Math.PI; // Some minimal math functionality borrowed from THREE.Math and stripped down // for the purposes of this library. MathUtil.Vector2 = function( x, y ) { this.x = x || 0; this.y = y || 0; }; MathUtil.Vector2.prototype = { constructor: MathUtil.Vector2, set: function( x, y ) { this.x = x; this.y = y; return this; }, copy: function( v ) { this.x = v.x; this.y = v.y; return this; }, subVectors: function( a, b ) { this.x = a.x - b.x; this.y = a.y - b.y; return this; } }; MathUtil.Vector3 = function( x, y, z ) { this.x = x || 0; this.y = y || 0; this.z = z || 0; }; MathUtil.Vector3.prototype = { constructor: MathUtil.Vector3, set: function( x, y, z ) { this.x = x; this.y = y; this.z = z; return this; }, copy: function( v ) { this.x = v.x; this.y = v.y; this.z = v.z; return this; }, length: function() { return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); }, normalize: function() { const scalar = this.length(); if ( scalar !== 0 ) { const invScalar = 1 / scalar; this.multiplyScalar(invScalar); } else { this.x = 0; this.y = 0; this.z = 0; } return this; }, multiplyScalar: function( scalar ) { this.x *= scalar; this.y *= scalar; this.z *= scalar; }, applyQuaternion: function( q ) { const x = this.x; const y = this.y; const z = this.z; const qx = q.x; const qy = q.y; const qz = q.z; const qw = q.w; // calculate quat * vector 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; // calculate result * inverse quat 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; }, dot: function( v ) { return this.x * v.x + this.y * v.y + this.z * v.z; }, crossVectors: function( a, b ) { const ax = a.x; const ay = a.y; const az = a.z; const bx = b.x; const by = b.y; const bz = b.z; this.x = ay * bz - az * by; this.y = az * bx - ax * bz; this.z = ax * by - ay * bx; return this; } }; MathUtil.Quaternion = function( x, y, z, w ) { this.x = x || 0; this.y = y || 0; this.z = z || 0; this.w = ( w !== undefined ) ? w : 1; }; MathUtil.Quaternion.prototype = { constructor: MathUtil.Quaternion, set: function( x, y, z, w ) { this.x = x; this.y = y; this.z = z; this.w = w; return this; }, copy: function( quaternion ) { this.x = quaternion.x; this.y = quaternion.y; this.z = quaternion.z; this.w = quaternion.w; return this; }, setFromEulerXYZ: function( x, y, z ) { const c1 = Math.cos( x / 2 ); const c2 = Math.cos( y / 2 ); const c3 = Math.cos( z / 2 ); const s1 = Math.sin( x / 2 ); const s2 = Math.sin( y / 2 ); const s3 = Math.sin( z / 2 ); this.x = s1 * c2 * c3 + c1 * s2 * s3; this.y = c1 * s2 * c3 - s1 * c2 * s3; this.z = c1 * c2 * s3 + s1 * s2 * c3; this.w = c1 * c2 * c3 - s1 * s2 * s3; return this; }, setFromEulerYXZ: function( x, y, z ) { const c1 = Math.cos( x / 2 ); const c2 = Math.cos( y / 2 ); const c3 = Math.cos( z / 2 ); const s1 = Math.sin( x / 2 ); const s2 = Math.sin( y / 2 ); const s3 = Math.sin( z / 2 ); this.x = s1 * c2 * c3 + c1 * s2 * s3; this.y = c1 * s2 * c3 - s1 * c2 * s3; this.z = c1 * c2 * s3 - s1 * s2 * c3; this.w = c1 * c2 * c3 + s1 * s2 * s3; return this; }, setFromAxisAngle: function( axis, angle ) { // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm // assumes axis is normalized const halfAngle = angle / 2; const s = Math.sin( halfAngle ); this.x = axis.x * s; this.y = axis.y * s; this.z = axis.z * s; this.w = Math.cos( halfAngle ); return this; }, multiply: function( q ) { return this.multiplyQuaternions( this, q ); }, multiplyQuaternions: function( a, b ) { // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm const qax = a.x; const qay = a.y; const qaz = a.z; const qaw = a.w; const qbx = b.x; const qby = b.y; const qbz = b.z; const qbw = b.w; this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; return this; }, inverse: function() { this.x *= -1; this.y *= -1; this.z *= -1; this.normalize(); return this; }, normalize: function() { let l = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); if ( l === 0 ) { this.x = 0; this.y = 0; this.z = 0; this.w = 1; } else { l = 1 / l; this.x = this.x * l; this.y = this.y * l; this.z = this.z * l; this.w = this.w * l; } return this; }, slerp: function( qb, t ) { if ( t === 0 ) return this; if ( t === 1 ) return this.copy( qb ); const x = this.x; const y = this.y; const z = this.z; const w = this.w; // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ let cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z; if ( cosHalfTheta < 0 ) { this.w = - qb.w; this.x = - qb.x; this.y = - qb.y; this.z = - qb.z; cosHalfTheta = - cosHalfTheta; } else { this.copy( qb ); } if ( cosHalfTheta >= 1.0 ) { this.w = w; this.x = x; this.y = y; this.z = z; return this; } const halfTheta = Math.acos( cosHalfTheta ); const sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta ); if ( Math.abs( sinHalfTheta ) < 0.001 ) { this.w = 0.5 * ( w + this.w ); this.x = 0.5 * ( x + this.x ); this.y = 0.5 * ( y + this.y ); this.z = 0.5 * ( z + this.z ); return this; } const ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta; const ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; this.w = ( w * ratioA + this.w * ratioB ); this.x = ( x * ratioA + this.x * ratioB ); this.y = ( y * ratioA + this.y * ratioB ); this.z = ( z * ratioA + this.z * ratioB ); return this; }, setFromUnitVectors: function() { // http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final // assumes direction vectors vFrom and vTo are normalized let v1; let r; const EPS = 0.000001; return function( vFrom, vTo ) { if ( v1 === undefined ) v1 = new MathUtil.Vector3(); r = vFrom.dot( vTo ) + 1; if ( r < EPS ) { r = 0; if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { v1.set( - vFrom.y, vFrom.x, 0 ); } else { v1.set( 0, - vFrom.z, vFrom.y ); } } else { v1.crossVectors( vFrom, vTo ); } this.x = v1.x; this.y = v1.y; this.z = v1.z; this.w = r; this.normalize(); return this; }; }() }; export default MathUtil;