A value type implementing a quaternion used by the HumanoidRetargeter. It provides constructors from components and an axis-angle, arithmetic operators, normalization, inverse, dot, rotation application, and an Identity constant.
/* * C# / XNA port of Bullet (c) 2011 Mark Neale <[email protected]> * * Bullet Continuous Collision Detection and Physics Library * Copyright (c) 2003-2008 Erwin Coumans http://www.bulletphysics.com/ * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ // Adapted from BulletXNA 73b2e1b9: namespace isolation, no XNA rendering, one type per file. #nullable disable #pragma warning disable CS1591, CS0168, CS0219, CS0414, CS0660, CS0661, CS0659, CS0693, CS8981, CS0108, CS0114 using System; using System.Diagnostics; namespace HumanoidRetargeter.Core.Formats.Mmd.Bullet.LinearMath; internal struct IndexedQuaternion { public IndexedQuaternion(float x, float y, float z, float w) { X = x; Y = y; Z = z; W = w; } public IndexedQuaternion(IndexedVector3 axis, float angle) { //SetRotation(ref axis, angle); float d = axis.Length(); { } float halfAngle = angle * 0.5f; float s = (float)Math.Sin(halfAngle) / d; X = axis.X * s; Y = axis.Y * s; Z = axis.Z * s; W = (float)Math.Cos(halfAngle); } public void SetRotation(ref IndexedVector3 axis, float angle) { float d = axis.Length(); { } float halfAngle = angle * 0.5f; float s = (float)Math.Sin(halfAngle) / d; X = axis.X * s; Y = axis.Y * s; Z = axis.Z * s; W = (float)Math.Cos(halfAngle); } public void SetValue(float x, float y, float z, float w) { X = x; Y = y; Z = z; W = w; } public static IndexedQuaternion operator +(IndexedQuaternion quaternion1, IndexedQuaternion quaternion2) { IndexedQuaternion quaternion; quaternion.X = quaternion1.X + quaternion2.X; quaternion.Y = quaternion1.Y + quaternion2.Y; quaternion.Z = quaternion1.Z + quaternion2.Z; quaternion.W = quaternion1.W + quaternion2.W; return quaternion; } public static IndexedQuaternion operator -(IndexedQuaternion quaternion1, IndexedQuaternion quaternion2) { IndexedQuaternion quaternion; quaternion.X = quaternion1.X - quaternion2.X; quaternion.Y = quaternion1.Y - quaternion2.Y; quaternion.Z = quaternion1.Z - quaternion2.Z; quaternion.W = quaternion1.W - quaternion2.W; return quaternion; } public static IndexedQuaternion operator *(IndexedQuaternion q1, IndexedQuaternion q2) { return new IndexedQuaternion(q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y, q1.W * q2.Y + q1.Y * q2.W + q1.Z * q2.X - q1.X * q2.Z, q1.W * q2.Z + q1.Z * q2.W + q1.X * q2.Y - q1.Y * q2.X, q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z); } public static IndexedQuaternion operator *(IndexedQuaternion q1, IndexedVector3 v1) { return new IndexedQuaternion(q1.W * v1.X + q1.Y * v1.Z - q1.Z * v1.Y, q1.W * v1.Y + q1.Z * v1.X - q1.X * v1.Z, q1.W * v1.Z + q1.X * v1.Y - q1.Y * v1.X, -q1.X * v1.X - q1.Y * v1.Y - q1.Z * v1.Z); } public static IndexedQuaternion operator *(IndexedVector3 v1, IndexedQuaternion q1) { return new IndexedQuaternion(v1.X * q1.W + v1.Y * q1.Z - v1.Z * q1.Y, v1.Y * q1.W + v1.Z * q1.X - v1.X * q1.Z, v1.Z * q1.W + v1.X * q1.Y - v1.Y * q1.X, -v1.X * q1.X - v1.Y * q1.Y - v1.Z * q1.Z); } public static IndexedQuaternion operator -(IndexedQuaternion value) { IndexedQuaternion q; q.X = -value.X; q.Y = -value.Y; q.Z = -value.Z; q.W = -value.W; return q; } public float LengthSquared() { return (float)(this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W); } public float Length() { return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W); } public void Normalize() { float num = 1f / (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W); this.X *= num; this.Y *= num; this.Z *= num; this.W *= num; } public static IndexedQuaternion Inverse(IndexedQuaternion q) { return new IndexedQuaternion(-q.X, -q.Y, -q.Z, q.W); } public IndexedQuaternion Inverse() { return new IndexedQuaternion(-X, -Y, -Z, W); } public float Dot(IndexedQuaternion q) { return X * q.X + Y * q.Y + Z * q.Z + W * q.W; } public static float Dot(IndexedQuaternion q, IndexedQuaternion q2) { return q.X * q2.X + q.Y * q2.Y + q.Z * q2.Z + q.W * q2.W; } public static bool operator ==(IndexedQuaternion value1, IndexedQuaternion value2) { if (value1.X == value2.X && value1.Y == value2.Y && value1.Z == value2.Z) return value1.W == value2.W; else return false; } public static bool operator !=(IndexedQuaternion value1, IndexedQuaternion value2) { if (value1.X == value2.X && value1.Y == value2.Y && value1.Z == value2.Z) return value1.W != value2.W; else return true; } public IndexedVector3 QuatRotate(IndexedQuaternion rotation, IndexedVector3 v) { IndexedQuaternion q = rotation * v; q *= rotation.Inverse(); return new IndexedVector3(q.X, q.Y, q.Z); } public float X; public float Y; public float Z; public float W; public static IndexedQuaternion Identity { get { return _identity; } } private static IndexedQuaternion _identity = new IndexedQuaternion(0, 0, 0, 1); }