Code/HumanoidRetargeter/Core/Formats/Mmd/Bullet/LinearMath/IndexedQuaternion.cs

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.

Native Interop
/*
 * 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);
}