From e9d314ab38c7b3f3da0c10794352efa5c949e9e8 Mon Sep 17 00:00:00 2001 From: Alexander Rose <alexander.rose@weirdbyte.de> Date: Wed, 11 Jul 2018 19:33:22 -0700 Subject: [PATCH] Vec3 improvements (slerp, exactEquals, equals) --- src/mol-math/linear-algebra/3d/vec3.ts | 32 ++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/mol-math/linear-algebra/3d/vec3.ts b/src/mol-math/linear-algebra/3d/vec3.ts index 071ce1785..1d87731d1 100644 --- a/src/mol-math/linear-algebra/3d/vec3.ts +++ b/src/mol-math/linear-algebra/3d/vec3.ts @@ -18,8 +18,8 @@ */ import Mat4 from './mat4'; -import { Quat, Mat3 } from '../3d'; -import { spline as _spline } from '../../interpolate' +import { Quat, Mat3, EPSILON } from '../3d'; +import { spline as _spline, clamp } from '../../interpolate' interface Vec3 extends Array<number> { [d: number]: number, '@type': 'vec3', length: 3 } @@ -124,6 +124,7 @@ namespace Vec3 { return out; } + /** Scales b, then adds a and b together */ export function scaleAndAdd(out: Vec3, a: Vec3, b: Vec3, scale: number) { out[0] = a[0] + (b[0] * scale); out[1] = a[1] + (b[1] * scale); @@ -244,6 +245,15 @@ namespace Vec3 { return out; } + const slerpRelVec = Vec3.zero() + export function slerp(out: Vec3, a: Vec3, b: Vec3, t: number) { + const dot = clamp(Vec3.dot(a, b), -1, 1); + const theta = Math.acos(dot) * t; + Vec3.scaleAndAdd(slerpRelVec, b, a, -dot); + Vec3.normalize(slerpRelVec, slerpRelVec); + return Vec3.add(out, Vec3.scale(out, a, Math.cos(theta)), Vec3.scale(slerpRelVec, slerpRelVec, Math.sin(theta))); + } + /** * Performs a hermite interpolation with two control points */ @@ -368,6 +378,24 @@ namespace Vec3 { } } + /** + * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) + */ + export function exactEquals(a: Vec3, b: Vec3) { + return a[0] === b[0] && a[1] === b[1] && a[2] === b[2]; + } + + /** + * Returns whether or not the vectors have approximately the same elements in the same position. + */ + export function equals(a: Vec3, b: Vec3) { + const a0 = a[0], a1 = a[1], a2 = a[2]; + const b0 = b[0], b1 = b[1], b2 = b[2]; + return (Math.abs(a0 - b0) <= EPSILON.Value * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && + Math.abs(a1 - b1) <= EPSILON.Value * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && + Math.abs(a2 - b2) <= EPSILON.Value * Math.max(1.0, Math.abs(a2), Math.abs(b2))); + } + const rotTemp = zero(); export function makeRotation(mat: Mat4, a: Vec3, b: Vec3): Mat4 { const by = angle(a, b); -- GitLab