199 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C#
		
	
	
| /*
 | |
|   Bullet for XNA Copyright (c) 2003-2007 Vsevolod Klementjev http://www.codeplex.com/xnadevru
 | |
|   Bullet original C++ version Copyright (c) 2003-2007 Erwin Coumans http://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.
 | |
| */
 | |
| 
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Text;
 | |
| 
 | |
| namespace XnaDevRu.BulletX.LinearMath
 | |
| {
 | |
| 	internal class Quaternion : QuadWord
 | |
| 	{
 | |
| 		public Quaternion() { }
 | |
| 
 | |
| 		public Quaternion(float x, float y, float z, float w)
 | |
| 			: base(x, y, z, w) { }
 | |
| 
 | |
| 		public Quaternion(Vector3 axis, float angle)
 | |
| 		{
 | |
| 			SetRotation(axis, angle);
 | |
| 		}
 | |
| 
 | |
| 		public Quaternion(float yaw, float pitch, float roll)
 | |
| 		{
 | |
| 			SetEuler(yaw, pitch, roll);
 | |
| 		}
 | |
| 
 | |
| 		public void SetRotation(Vector3 axis, float angle)
 | |
| 		{
 | |
| 			float d = axis.Length();
 | |
| 			if (d == 0) throw new DivideByZeroException();
 | |
| 			float s = (float)Math.Sin(angle * 0.5f) / d;
 | |
| 			X = axis.X * s;
 | |
| 			Y = axis.Y * s;
 | |
| 			Z = axis.Z * s;
 | |
| 			W = (float)Math.Cos(angle * 0.5f);
 | |
| 		}
 | |
| 
 | |
| 		public void SetEuler(float yaw, float pitch, float roll)
 | |
| 		{
 | |
| 			float halfYaw = yaw * 0.5f;
 | |
| 			float halfPitch = pitch * 0.5f;
 | |
| 			float halfRoll = roll * 0.5f;
 | |
| 			float cosYaw = (float)Math.Cos(halfYaw);
 | |
| 			float sinYaw = (float)Math.Sin(halfYaw);
 | |
| 			float cosPitch = (float)Math.Cos(halfPitch);
 | |
| 			float sinPitch = (float)Math.Sin(halfPitch);
 | |
| 			float cosRoll = (float)Math.Cos(halfRoll);
 | |
| 			float sinRoll = (float)Math.Sin(halfRoll);
 | |
| 			X = cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw;
 | |
| 			Y = cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw;
 | |
| 			Z = sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw;
 | |
| 			W = cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw;
 | |
| 		}
 | |
| 
 | |
| 		public float LengthSquared()
 | |
| 		{
 | |
| 			return Dot(this, this);
 | |
| 		}
 | |
| 
 | |
| 		public float Length()
 | |
| 		{
 | |
| 			return (float)Math.Sqrt(LengthSquared());
 | |
| 		}
 | |
| 
 | |
| 		public float Angle()
 | |
| 		{
 | |
| 			return 2f * (float)Math.Acos(W);
 | |
| 		}
 | |
| 
 | |
| 		public static float Angle(Quaternion a, Quaternion b)
 | |
| 		{
 | |
| 			float s = (float)Math.Sqrt(a.LengthSquared() * b.LengthSquared());
 | |
| 			if (s == 0) throw new DivideByZeroException();
 | |
| 			return (float)Math.Acos(Dot(a, b) / s);
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion Farthest(Quaternion a, Quaternion b)
 | |
| 		{
 | |
| 			Quaternion diff, sum;
 | |
| 			diff = a - b;
 | |
| 			sum = a + b;
 | |
| 			if (Dot(diff, diff) > Dot(sum, sum))
 | |
| 				return b;
 | |
| 			return -b;
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion Slerp(Quaternion a, Quaternion b, float c)
 | |
| 		{
 | |
| 			float theta = Angle(a, b);
 | |
| 			if (theta != 0)
 | |
| 			{
 | |
| 				float d = 1f / (float)Math.Sin(theta);
 | |
| 				float s0 = (float)Math.Sin((1f - c) * theta);
 | |
| 				float s1 = (float)Math.Sin(c * theta);
 | |
| 				return new Quaternion(
 | |
| 					(a.X * s0 + b.X * s1) * d,
 | |
| 					(a.Y * s0 + b.Y * s1) * d,
 | |
| 					(a.Z * s0 + b.Z * s1) * d,
 | |
| 					(a.W * s0 + b.W * s1) * d);
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				return a;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion Inverse(Quaternion a)
 | |
| 		{
 | |
| 			return new Quaternion(a.X, a.Y, a.Z, -a.W);
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion Normalize(Quaternion a)
 | |
| 		{
 | |
| 			return a / a.Length();
 | |
| 		}
 | |
| 
 | |
| 		public static float Dot(Quaternion a, Quaternion b)
 | |
| 		{
 | |
| 			return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion operator +(Quaternion a, Quaternion b)
 | |
| 		{
 | |
| 			return new Quaternion(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion operator -(Quaternion a, Quaternion b)
 | |
| 		{
 | |
| 			return new Quaternion(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion operator -(Quaternion a)
 | |
| 		{
 | |
| 			return new Quaternion(-a.X, -a.Y, -a.Z, -a.W);
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion operator *(Quaternion a, float b)
 | |
| 		{
 | |
| 			return new Quaternion(a.X * b, a.Y * b, a.Z * b, a.W * b);
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion operator *(Quaternion a, Quaternion b)
 | |
| 		{
 | |
| 			return new Quaternion(
 | |
| 				a.W * b.X + a.X * b.W + a.Y * b.Z - a.Z * b.Y,
 | |
| 				a.W * b.Y + a.Y * b.W + a.Z * b.X - a.X * b.Z,
 | |
| 				a.W * b.Z + a.Z * b.W + a.X * b.Y - a.Y * b.X,
 | |
| 				a.W * b.W - a.X * b.X - a.Y * b.Y - a.Z * b.Z);
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion operator *(Quaternion a, Vector3 b)
 | |
| 		{
 | |
| 			return new Quaternion(
 | |
| 				a.W * b.X + a.Y * b.Z - a.Z * b.Y,
 | |
| 				a.W * b.Y + a.Z * b.X - a.X * b.Z,
 | |
| 				a.W * b.Z + a.X * b.Y - a.Y * b.X,
 | |
| 				-a.X * b.X - a.Y * b.Y - a.Z * b.Z);
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion operator *(Vector3 w, Quaternion q)
 | |
| 		{
 | |
| 			return new Quaternion(
 | |
| 				w.X * q.W + w.Y * q.Z - w.Z * q.Y,
 | |
| 				w.Y * q.W + w.Z * q.X - w.X * q.Z,
 | |
| 				w.Z * q.W + w.X * q.Y - w.Y * q.X,
 | |
| 				-w.X * q.X - w.Y * q.Y - w.Z * q.Z);
 | |
| 		}
 | |
| 
 | |
| 		public static Quaternion operator /(Quaternion a, float b)
 | |
| 		{
 | |
| 			if (b == 0) throw new DivideByZeroException();
 | |
| 			return new Quaternion(a.X / b, a.Y / b, a.Z / b, a.W / b);
 | |
| 		}
 | |
| 
 | |
| 		public static explicit operator MonoXnaCompactMaths.Quaternion(Quaternion a)
 | |
| 		{
 | |
| 			return new MonoXnaCompactMaths.Quaternion(a.X, a.Y, a.Z, a.W);
 | |
| 		}
 | |
| 	}
 | |
| }
 |