@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
text/typescript
/* 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;