From 646ca67e7edb9d964dc2797d76093ac4d7b8f75c Mon Sep 17 00:00:00 2001 From: kovacsv Date: Sat, 15 Jan 2022 12:11:52 +0100 Subject: [PATCH] Create quaternion from x, y, z rotation values. --- source/engine/geometry/quaternion.js | 55 ++++++++++++++++++++++++++++ source/engine/main.js | 4 +- test/tests/geometry_test.js | 13 ++++++- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/source/engine/geometry/quaternion.js b/source/engine/geometry/quaternion.js index fbc7d9a..d94f9ad 100644 --- a/source/engine/geometry/quaternion.js +++ b/source/engine/geometry/quaternion.js @@ -1,3 +1,5 @@ +import { IsEqual } from './geometry.js'; + export class Quaternion { constructor (x, y, z, w) @@ -9,6 +11,11 @@ export class Quaternion } } +export function QuaternionIsEqual (a, b) +{ + return IsEqual (a.x, b.x) && IsEqual (a.y, b.y) && IsEqual (a.z, b.z) && IsEqual (a.w, b.w); +} + export function ArrayToQuaternion (arr) { return new Quaternion (arr[0], arr[1], arr[2], arr[3]); @@ -26,3 +33,51 @@ export function QuaternionFromAxisAngle (axis, angle) Math.cos (a) ); } + +export function QuaternionFromXYZ (x, y, z, mode) { + + const c1 = Math.cos (x / 2.0); + const c2 = Math.cos (y / 2.0); + const c3 = Math.cos (z / 2.0); + + const s1 = Math.sin (x / 2.0); + const s2 = Math.sin (y / 2.0); + const s3 = Math.sin (z / 2.0); + + let quaternion = new Quaternion (0.0, 0.0, 0.0, 1.0); + if (mode === 'XYZ') { + quaternion.x = s1 * c2 * c3 + c1 * s2 * s3; + quaternion.y = c1 * s2 * c3 - s1 * c2 * s3; + quaternion.z = c1 * c2 * s3 + s1 * s2 * c3; + quaternion.w = c1 * c2 * c3 - s1 * s2 * s3; + } else if (mode === 'YXZ') { + quaternion.x = s1 * c2 * c3 + c1 * s2 * s3; + quaternion.y = c1 * s2 * c3 - s1 * c2 * s3; + quaternion.z = c1 * c2 * s3 - s1 * s2 * c3; + quaternion.w = c1 * c2 * c3 + s1 * s2 * s3; + } else if (mode === 'ZXY') { + quaternion.x = s1 * c2 * c3 - c1 * s2 * s3; + quaternion.y = c1 * s2 * c3 + s1 * c2 * s3; + quaternion.z = c1 * c2 * s3 + s1 * s2 * c3; + quaternion.w = c1 * c2 * c3 - s1 * s2 * s3; + } else if (mode === 'ZYX') { + quaternion.x = s1 * c2 * c3 - c1 * s2 * s3; + quaternion.y = c1 * s2 * c3 + s1 * c2 * s3; + quaternion.z = c1 * c2 * s3 - s1 * s2 * c3; + quaternion.w = c1 * c2 * c3 + s1 * s2 * s3; + } else if (mode === 'YZX') { + quaternion.x = s1 * c2 * c3 + c1 * s2 * s3; + quaternion.y = c1 * s2 * c3 + s1 * c2 * s3; + quaternion.z = c1 * c2 * s3 - s1 * s2 * c3; + quaternion.w = c1 * c2 * c3 - s1 * s2 * s3; + } else if (mode === 'XZY') { + quaternion.x = s1 * c2 * c3 - c1 * s2 * s3; + quaternion.y = c1 * s2 * c3 - s1 * c2 * s3; + quaternion.z = c1 * c2 * s3 + s1 * s2 * c3; + quaternion.w = c1 * c2 * c3 + s1 * s2 * s3; + } else { + return null; + } + + return quaternion; +} diff --git a/source/engine/main.js b/source/engine/main.js index ac929e6..3590fd0 100644 --- a/source/engine/main.js +++ b/source/engine/main.js @@ -16,7 +16,7 @@ import { Coord4D } from './geometry/coord4d.js'; import { IsZero, IsLower, IsGreater, IsLowerOrEqual, IsGreaterOrEqual, IsEqual, IsEqualEps, IsPositive, IsNegative, Eps, BigEps, RadDeg, DegRad, Direction } from './geometry/geometry.js'; import { Matrix, MatrixIsEqual } from './geometry/matrix.js'; import { OctreeNode, Octree } from './geometry/octree.js'; -import { Quaternion, ArrayToQuaternion, QuaternionFromAxisAngle } from './geometry/quaternion.js'; +import { Quaternion, QuaternionIsEqual, ArrayToQuaternion, QuaternionFromAxisAngle, QuaternionFromXYZ } from './geometry/quaternion.js'; import { Transformation, TransformationIsEqual } from './geometry/transformation.js'; import { BezierTweenFunction, LinearTweenFunction, ParabolicTweenFunction, TweenCoord3D } from './geometry/tween.js'; import { File, FileList } from './import/filelist.js'; @@ -124,8 +124,10 @@ export { OctreeNode, Octree, Quaternion, + QuaternionIsEqual, ArrayToQuaternion, QuaternionFromAxisAngle, + QuaternionFromXYZ, Transformation, TransformationIsEqual, BezierTweenFunction, diff --git a/test/tests/geometry_test.js b/test/tests/geometry_test.js index 381fedd..b6bc182 100644 --- a/test/tests/geometry_test.js +++ b/test/tests/geometry_test.js @@ -40,7 +40,6 @@ describe ('Comparison', function () { }); }); - describe ('Coord', function () { it ('Length', function () { var c = new OV.Coord3D (2.0, 0.0, 0.0); @@ -64,6 +63,18 @@ describe ('Coord', function () { }); }); +describe ('Quaternion', function () { + it ('Create Quaternion', function () { + let q1 = OV.QuaternionFromAxisAngle (new OV.Coord3D (1.0, 0.0, 0.0), Math.PI / 2.0); + let q2 = OV.QuaternionFromXYZ (Math.PI / 2.0, 0.0, 0.0, 'XYZ'); + assert.ok (OV.QuaternionIsEqual (q1, q2)); + assert.ok (OV.IsEqual (q1.x, 0.7071067811865475)); + assert.ok (OV.IsEqual (q1.y, 0.0)); + assert.ok (OV.IsEqual (q1.z, 0.0)); + assert.ok (OV.IsEqual (q1.w, 0.7071067811865475)); + }); +}); + describe ('Triangle', function() { it ('Calculate Normal', function () { var normal = OV.CalculateTriangleNormal (