Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1452 | chris | 1 | #region --- License --- |
| 2 | /* |
||
| 3 | Copyright (c) 2006 - 2008 The Open Toolkit library. |
||
| 4 | |||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of |
||
| 6 | this software and associated documentation files (the "Software"), to deal in |
||
| 7 | the Software without restriction, including without limitation the rights to |
||
| 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
||
| 9 | of the Software, and to permit persons to whom the Software is furnished to do |
||
| 10 | so, subject to the following conditions: |
||
| 11 | |||
| 12 | The above copyright notice and this permission notice shall be included in all |
||
| 13 | copies or substantial portions of the Software. |
||
| 14 | |||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||
| 21 | SOFTWARE. |
||
| 22 | */ |
||
| 23 | #endregion |
||
| 24 | |||
| 25 | using System; |
||
| 26 | using System.Runtime.InteropServices; |
||
| 27 | using System.ComponentModel; |
||
| 28 | using System.Xml.Serialization; |
||
| 29 | |||
| 30 | namespace OpenTK |
||
| 31 | { |
||
| 32 | /// <summary> |
||
| 33 | /// Represents a Quaternion. |
||
| 34 | /// </summary> |
||
| 35 | [Serializable] |
||
| 36 | [StructLayout(LayoutKind.Sequential)] |
||
| 37 | public struct Quaternion : IEquatable<Quaternion> |
||
| 38 | { |
||
| 39 | #region Fields |
||
| 40 | |||
| 41 | Vector3 xyz; |
||
| 42 | float w; |
||
| 43 | |||
| 44 | #endregion |
||
| 45 | |||
| 46 | #region Constructors |
||
| 47 | |||
| 48 | /// <summary> |
||
| 49 | /// Construct a new Quaternion from vector and w components |
||
| 50 | /// </summary> |
||
| 51 | /// <param name="v">The vector part</param> |
||
| 52 | /// <param name="w">The w part</param> |
||
| 53 | public Quaternion(Vector3 v, float w) |
||
| 54 | { |
||
| 55 | this.xyz = v; |
||
| 56 | this.w = w; |
||
| 57 | } |
||
| 58 | |||
| 59 | /// <summary> |
||
| 60 | /// Construct a new Quaternion |
||
| 61 | /// </summary> |
||
| 62 | /// <param name="x">The x component</param> |
||
| 63 | /// <param name="y">The y component</param> |
||
| 64 | /// <param name="z">The z component</param> |
||
| 65 | /// <param name="w">The w component</param> |
||
| 66 | public Quaternion(float x, float y, float z, float w) |
||
| 67 | : this(new Vector3(x, y, z), w) |
||
| 68 | { } |
||
| 69 | |||
| 70 | #endregion |
||
| 71 | |||
| 72 | #region Public Members |
||
| 73 | |||
| 74 | #region Properties |
||
| 75 | |||
| 76 | /// <summary> |
||
| 77 | /// Gets or sets an OpenTK.Vector3 with the X, Y and Z components of this instance. |
||
| 78 | /// </summary> |
||
| 79 | [Obsolete("Use Xyz property instead.")] |
||
| 80 | [CLSCompliant(false)] |
||
| 81 | [EditorBrowsable(EditorBrowsableState.Never)] |
||
| 82 | [XmlIgnore] |
||
| 83 | public Vector3 XYZ { get { return Xyz; } set { Xyz = value; } } |
||
| 84 | |||
| 85 | /// <summary> |
||
| 86 | /// Gets or sets an OpenTK.Vector3 with the X, Y and Z components of this instance. |
||
| 87 | /// </summary> |
||
| 88 | public Vector3 Xyz { get { return xyz; } set { xyz = value; } } |
||
| 89 | |||
| 90 | /// <summary> |
||
| 91 | /// Gets or sets the X component of this instance. |
||
| 92 | /// </summary> |
||
| 93 | [XmlIgnore] |
||
| 94 | public float X { get { return xyz.X; } set { xyz.X = value; } } |
||
| 95 | |||
| 96 | /// <summary> |
||
| 97 | /// Gets or sets the Y component of this instance. |
||
| 98 | /// </summary> |
||
| 99 | [XmlIgnore] |
||
| 100 | public float Y { get { return xyz.Y; } set { xyz.Y = value; } } |
||
| 101 | |||
| 102 | /// <summary> |
||
| 103 | /// Gets or sets the Z component of this instance. |
||
| 104 | /// </summary> |
||
| 105 | [XmlIgnore] |
||
| 106 | public float Z { get { return xyz.Z; } set { xyz.Z = value; } } |
||
| 107 | |||
| 108 | /// <summary> |
||
| 109 | /// Gets or sets the W component of this instance. |
||
| 110 | /// </summary> |
||
| 111 | public float W { get { return w; } set { w = value; } } |
||
| 112 | |||
| 113 | #endregion |
||
| 114 | |||
| 115 | #region Instance |
||
| 116 | |||
| 117 | #region ToAxisAngle |
||
| 118 | |||
| 119 | /// <summary> |
||
| 120 | /// Convert the current quaternion to axis angle representation |
||
| 121 | /// </summary> |
||
| 122 | /// <param name="axis">The resultant axis</param> |
||
| 123 | /// <param name="angle">The resultant angle</param> |
||
| 124 | public void ToAxisAngle(out Vector3 axis, out float angle) |
||
| 125 | { |
||
| 126 | Vector4 result = ToAxisAngle(); |
||
| 127 | axis = result.Xyz; |
||
| 128 | angle = result.W; |
||
| 129 | } |
||
| 130 | |||
| 131 | /// <summary> |
||
| 132 | /// Convert this instance to an axis-angle representation. |
||
| 133 | /// </summary> |
||
| 134 | /// <returns>A Vector4 that is the axis-angle representation of this quaternion.</returns> |
||
| 135 | public Vector4 ToAxisAngle() |
||
| 136 | { |
||
| 137 | Quaternion q = this; |
||
| 138 | if (q.W > 1.0f) |
||
| 139 | q.Normalize(); |
||
| 140 | |||
| 141 | Vector4 result = new Vector4(); |
||
| 142 | |||
| 143 | result.W = 2.0f * (float)System.Math.Acos(q.W); // angle |
||
| 144 | float den = (float)System.Math.Sqrt(1.0 - q.W * q.W); |
||
| 145 | if (den > 0.0001f) |
||
| 146 | { |
||
| 147 | result.Xyz = q.Xyz / den; |
||
| 148 | } |
||
| 149 | else |
||
| 150 | { |
||
| 151 | // This occurs when the angle is zero. |
||
| 152 | // Not a problem: just set an arbitrary normalized axis. |
||
| 153 | result.Xyz = Vector3.UnitX; |
||
| 154 | } |
||
| 155 | |||
| 156 | return result; |
||
| 157 | } |
||
| 158 | |||
| 159 | #endregion |
||
| 160 | |||
| 161 | #region public float Length |
||
| 162 | |||
| 163 | /// <summary> |
||
| 164 | /// Gets the length (magnitude) of the quaternion. |
||
| 165 | /// </summary> |
||
| 166 | /// <seealso cref="LengthSquared"/> |
||
| 167 | public float Length |
||
| 168 | { |
||
| 169 | get |
||
| 170 | { |
||
| 171 | return (float)System.Math.Sqrt(W * W + Xyz.LengthSquared); |
||
| 172 | } |
||
| 173 | } |
||
| 174 | |||
| 175 | #endregion |
||
| 176 | |||
| 177 | #region public float LengthSquared |
||
| 178 | |||
| 179 | /// <summary> |
||
| 180 | /// Gets the square of the quaternion length (magnitude). |
||
| 181 | /// </summary> |
||
| 182 | public float LengthSquared |
||
| 183 | { |
||
| 184 | get |
||
| 185 | { |
||
| 186 | return W * W + Xyz.LengthSquared; |
||
| 187 | } |
||
| 188 | } |
||
| 189 | |||
| 190 | #endregion |
||
| 191 | |||
| 192 | #region public void Normalize() |
||
| 193 | |||
| 194 | /// <summary> |
||
| 195 | /// Scales the Quaternion to unit length. |
||
| 196 | /// </summary> |
||
| 197 | public void Normalize() |
||
| 198 | { |
||
| 199 | float scale = 1.0f / this.Length; |
||
| 200 | Xyz *= scale; |
||
| 201 | W *= scale; |
||
| 202 | } |
||
| 203 | |||
| 204 | #endregion |
||
| 205 | |||
| 206 | #region public void Conjugate() |
||
| 207 | |||
| 208 | /// <summary> |
||
| 209 | /// Convert this quaternion to its conjugate |
||
| 210 | /// </summary> |
||
| 211 | public void Conjugate() |
||
| 212 | { |
||
| 213 | Xyz = -Xyz; |
||
| 214 | } |
||
| 215 | |||
| 216 | #endregion |
||
| 217 | |||
| 218 | #endregion |
||
| 219 | |||
| 220 | #region Static |
||
| 221 | |||
| 222 | #region Fields |
||
| 223 | |||
| 224 | /// <summary> |
||
| 225 | /// Defines the identity quaternion. |
||
| 226 | /// </summary> |
||
| 227 | public static Quaternion Identity = new Quaternion(0, 0, 0, 1); |
||
| 228 | |||
| 229 | #endregion |
||
| 230 | |||
| 231 | #region Add |
||
| 232 | |||
| 233 | /// <summary> |
||
| 234 | /// Add two quaternions |
||
| 235 | /// </summary> |
||
| 236 | /// <param name="left">The first operand</param> |
||
| 237 | /// <param name="right">The second operand</param> |
||
| 238 | /// <returns>The result of the addition</returns> |
||
| 239 | public static Quaternion Add(Quaternion left, Quaternion right) |
||
| 240 | { |
||
| 241 | return new Quaternion( |
||
| 242 | left.Xyz + right.Xyz, |
||
| 243 | left.W + right.W); |
||
| 244 | } |
||
| 245 | |||
| 246 | /// <summary> |
||
| 247 | /// Add two quaternions |
||
| 248 | /// </summary> |
||
| 249 | /// <param name="left">The first operand</param> |
||
| 250 | /// <param name="right">The second operand</param> |
||
| 251 | /// <param name="result">The result of the addition</param> |
||
| 252 | public static void Add(ref Quaternion left, ref Quaternion right, out Quaternion result) |
||
| 253 | { |
||
| 254 | result = new Quaternion( |
||
| 255 | left.Xyz + right.Xyz, |
||
| 256 | left.W + right.W); |
||
| 257 | } |
||
| 258 | |||
| 259 | #endregion |
||
| 260 | |||
| 261 | #region Sub |
||
| 262 | |||
| 263 | /// <summary> |
||
| 264 | /// Subtracts two instances. |
||
| 265 | /// </summary> |
||
| 266 | /// <param name="left">The left instance.</param> |
||
| 267 | /// <param name="right">The right instance.</param> |
||
| 268 | /// <returns>The result of the operation.</returns> |
||
| 269 | public static Quaternion Sub(Quaternion left, Quaternion right) |
||
| 270 | { |
||
| 271 | return new Quaternion( |
||
| 272 | left.Xyz - right.Xyz, |
||
| 273 | left.W - right.W); |
||
| 274 | } |
||
| 275 | |||
| 276 | /// <summary> |
||
| 277 | /// Subtracts two instances. |
||
| 278 | /// </summary> |
||
| 279 | /// <param name="left">The left instance.</param> |
||
| 280 | /// <param name="right">The right instance.</param> |
||
| 281 | /// <param name="result">The result of the operation.</param> |
||
| 282 | public static void Sub(ref Quaternion left, ref Quaternion right, out Quaternion result) |
||
| 283 | { |
||
| 284 | result = new Quaternion( |
||
| 285 | left.Xyz - right.Xyz, |
||
| 286 | left.W - right.W); |
||
| 287 | } |
||
| 288 | |||
| 289 | #endregion |
||
| 290 | |||
| 291 | #region Mult |
||
| 292 | |||
| 293 | /// <summary> |
||
| 294 | /// Multiplies two instances. |
||
| 295 | /// </summary> |
||
| 296 | /// <param name="left">The first instance.</param> |
||
| 297 | /// <param name="right">The second instance.</param> |
||
| 298 | /// <returns>A new instance containing the result of the calculation.</returns> |
||
| 299 | [Obsolete("Use Multiply instead.")] |
||
| 300 | public static Quaternion Mult(Quaternion left, Quaternion right) |
||
| 301 | { |
||
| 302 | return new Quaternion( |
||
| 303 | right.W * left.Xyz + left.W * right.Xyz + Vector3.Cross(left.Xyz, right.Xyz), |
||
| 304 | left.W * right.W - Vector3.Dot(left.Xyz, right.Xyz)); |
||
| 305 | } |
||
| 306 | |||
| 307 | /// <summary> |
||
| 308 | /// Multiplies two instances. |
||
| 309 | /// </summary> |
||
| 310 | /// <param name="left">The first instance.</param> |
||
| 311 | /// <param name="right">The second instance.</param> |
||
| 312 | /// <param name="result">A new instance containing the result of the calculation.</param> |
||
| 313 | [Obsolete("Use Multiply instead.")] |
||
| 314 | public static void Mult(ref Quaternion left, ref Quaternion right, out Quaternion result) |
||
| 315 | { |
||
| 316 | result = new Quaternion( |
||
| 317 | right.W * left.Xyz + left.W * right.Xyz + Vector3.Cross(left.Xyz, right.Xyz), |
||
| 318 | left.W * right.W - Vector3.Dot(left.Xyz, right.Xyz)); |
||
| 319 | } |
||
| 320 | |||
| 321 | /// <summary> |
||
| 322 | /// Multiplies two instances. |
||
| 323 | /// </summary> |
||
| 324 | /// <param name="left">The first instance.</param> |
||
| 325 | /// <param name="right">The second instance.</param> |
||
| 326 | /// <returns>A new instance containing the result of the calculation.</returns> |
||
| 327 | public static Quaternion Multiply(Quaternion left, Quaternion right) |
||
| 328 | { |
||
| 329 | Quaternion result; |
||
| 330 | Multiply(ref left, ref right, out result); |
||
| 331 | return result; |
||
| 332 | } |
||
| 333 | |||
| 334 | /// <summary> |
||
| 335 | /// Multiplies two instances. |
||
| 336 | /// </summary> |
||
| 337 | /// <param name="left">The first instance.</param> |
||
| 338 | /// <param name="right">The second instance.</param> |
||
| 339 | /// <param name="result">A new instance containing the result of the calculation.</param> |
||
| 340 | public static void Multiply(ref Quaternion left, ref Quaternion right, out Quaternion result) |
||
| 341 | { |
||
| 342 | result = new Quaternion( |
||
| 343 | right.W * left.Xyz + left.W * right.Xyz + Vector3.Cross(left.Xyz, right.Xyz), |
||
| 344 | left.W * right.W - Vector3.Dot(left.Xyz, right.Xyz)); |
||
| 345 | } |
||
| 346 | |||
| 347 | /// <summary> |
||
| 348 | /// Multiplies an instance by a scalar. |
||
| 349 | /// </summary> |
||
| 350 | /// <param name="quaternion">The instance.</param> |
||
| 351 | /// <param name="scale">The scalar.</param> |
||
| 352 | /// <param name="result">A new instance containing the result of the calculation.</param> |
||
| 353 | public static void Multiply(ref Quaternion quaternion, float scale, out Quaternion result) |
||
| 354 | { |
||
| 355 | result = new Quaternion(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale); |
||
| 356 | } |
||
| 357 | |||
| 358 | /// <summary> |
||
| 359 | /// Multiplies an instance by a scalar. |
||
| 360 | /// </summary> |
||
| 361 | /// <param name="quaternion">The instance.</param> |
||
| 362 | /// <param name="scale">The scalar.</param> |
||
| 363 | /// <returns>A new instance containing the result of the calculation.</returns> |
||
| 364 | public static Quaternion Multiply(Quaternion quaternion, float scale) |
||
| 365 | { |
||
| 366 | return new Quaternion(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale); |
||
| 367 | } |
||
| 368 | |||
| 369 | #endregion |
||
| 370 | |||
| 371 | #region Conjugate |
||
| 372 | |||
| 373 | /// <summary> |
||
| 374 | /// Get the conjugate of the given quaternion |
||
| 375 | /// </summary> |
||
| 376 | /// <param name="q">The quaternion</param> |
||
| 377 | /// <returns>The conjugate of the given quaternion</returns> |
||
| 378 | public static Quaternion Conjugate(Quaternion q) |
||
| 379 | { |
||
| 380 | return new Quaternion(-q.Xyz, q.W); |
||
| 381 | } |
||
| 382 | |||
| 383 | /// <summary> |
||
| 384 | /// Get the conjugate of the given quaternion |
||
| 385 | /// </summary> |
||
| 386 | /// <param name="q">The quaternion</param> |
||
| 387 | /// <param name="result">The conjugate of the given quaternion</param> |
||
| 388 | public static void Conjugate(ref Quaternion q, out Quaternion result) |
||
| 389 | { |
||
| 390 | result = new Quaternion(-q.Xyz, q.W); |
||
| 391 | } |
||
| 392 | |||
| 393 | #endregion |
||
| 394 | |||
| 395 | #region Invert |
||
| 396 | |||
| 397 | /// <summary> |
||
| 398 | /// Get the inverse of the given quaternion |
||
| 399 | /// </summary> |
||
| 400 | /// <param name="q">The quaternion to invert</param> |
||
| 401 | /// <returns>The inverse of the given quaternion</returns> |
||
| 402 | public static Quaternion Invert(Quaternion q) |
||
| 403 | { |
||
| 404 | Quaternion result; |
||
| 405 | Invert(ref q, out result); |
||
| 406 | return result; |
||
| 407 | } |
||
| 408 | |||
| 409 | /// <summary> |
||
| 410 | /// Get the inverse of the given quaternion |
||
| 411 | /// </summary> |
||
| 412 | /// <param name="q">The quaternion to invert</param> |
||
| 413 | /// <param name="result">The inverse of the given quaternion</param> |
||
| 414 | public static void Invert(ref Quaternion q, out Quaternion result) |
||
| 415 | { |
||
| 416 | float lengthSq = q.LengthSquared; |
||
| 417 | if (lengthSq != 0.0) |
||
| 418 | { |
||
| 419 | float i = 1.0f / lengthSq; |
||
| 420 | result = new Quaternion(q.Xyz * -i, q.W * i); |
||
| 421 | } |
||
| 422 | else |
||
| 423 | { |
||
| 424 | result = q; |
||
| 425 | } |
||
| 426 | } |
||
| 427 | |||
| 428 | #endregion |
||
| 429 | |||
| 430 | #region Normalize |
||
| 431 | |||
| 432 | /// <summary> |
||
| 433 | /// Scale the given quaternion to unit length |
||
| 434 | /// </summary> |
||
| 435 | /// <param name="q">The quaternion to normalize</param> |
||
| 436 | /// <returns>The normalized quaternion</returns> |
||
| 437 | public static Quaternion Normalize(Quaternion q) |
||
| 438 | { |
||
| 439 | Quaternion result; |
||
| 440 | Normalize(ref q, out result); |
||
| 441 | return result; |
||
| 442 | } |
||
| 443 | |||
| 444 | /// <summary> |
||
| 445 | /// Scale the given quaternion to unit length |
||
| 446 | /// </summary> |
||
| 447 | /// <param name="q">The quaternion to normalize</param> |
||
| 448 | /// <param name="result">The normalized quaternion</param> |
||
| 449 | public static void Normalize(ref Quaternion q, out Quaternion result) |
||
| 450 | { |
||
| 451 | float scale = 1.0f / q.Length; |
||
| 452 | result = new Quaternion(q.Xyz * scale, q.W * scale); |
||
| 453 | } |
||
| 454 | |||
| 455 | #endregion |
||
| 456 | |||
| 457 | #region FromAxisAngle |
||
| 458 | |||
| 459 | /// <summary> |
||
| 460 | /// Build a quaternion from the given axis and angle |
||
| 461 | /// </summary> |
||
| 462 | /// <param name="axis">The axis to rotate about</param> |
||
| 463 | /// <param name="angle">The rotation angle in radians</param> |
||
| 464 | /// <returns></returns> |
||
| 465 | public static Quaternion FromAxisAngle(Vector3 axis, float angle) |
||
| 466 | { |
||
| 467 | if (axis.LengthSquared == 0.0f) |
||
| 468 | return Identity; |
||
| 469 | |||
| 470 | Quaternion result = Identity; |
||
| 471 | |||
| 472 | angle *= 0.5f; |
||
| 473 | axis.Normalize(); |
||
| 474 | result.Xyz = axis * (float)System.Math.Sin(angle); |
||
| 475 | result.W = (float)System.Math.Cos(angle); |
||
| 476 | |||
| 477 | return Normalize(result); |
||
| 478 | } |
||
| 479 | |||
| 480 | #endregion |
||
| 481 | |||
| 482 | #region Slerp |
||
| 483 | |||
| 484 | /// <summary> |
||
| 485 | /// Do Spherical linear interpolation between two quaternions |
||
| 486 | /// </summary> |
||
| 487 | /// <param name="q1">The first quaternion</param> |
||
| 488 | /// <param name="q2">The second quaternion</param> |
||
| 489 | /// <param name="blend">The blend factor</param> |
||
| 490 | /// <returns>A smooth blend between the given quaternions</returns> |
||
| 491 | public static Quaternion Slerp(Quaternion q1, Quaternion q2, float blend) |
||
| 492 | { |
||
| 493 | // if either input is zero, return the other. |
||
| 494 | if (q1.LengthSquared == 0.0f) |
||
| 495 | { |
||
| 496 | if (q2.LengthSquared == 0.0f) |
||
| 497 | { |
||
| 498 | return Identity; |
||
| 499 | } |
||
| 500 | return q2; |
||
| 501 | } |
||
| 502 | else if (q2.LengthSquared == 0.0f) |
||
| 503 | { |
||
| 504 | return q1; |
||
| 505 | } |
||
| 506 | |||
| 507 | |||
| 508 | float cosHalfAngle = q1.W * q2.W + Vector3.Dot(q1.Xyz, q2.Xyz); |
||
| 509 | |||
| 510 | if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f) |
||
| 511 | { |
||
| 512 | // angle = 0.0f, so just return one input. |
||
| 513 | return q1; |
||
| 514 | } |
||
| 515 | else if (cosHalfAngle < 0.0f) |
||
| 516 | { |
||
| 517 | q2.Xyz = -q2.Xyz; |
||
| 518 | q2.W = -q2.W; |
||
| 519 | cosHalfAngle = -cosHalfAngle; |
||
| 520 | } |
||
| 521 | |||
| 522 | float blendA; |
||
| 523 | float blendB; |
||
| 524 | if (cosHalfAngle < 0.99f) |
||
| 525 | { |
||
| 526 | // do proper slerp for big angles |
||
| 527 | float halfAngle = (float)System.Math.Acos(cosHalfAngle); |
||
| 528 | float sinHalfAngle = (float)System.Math.Sin(halfAngle); |
||
| 529 | float oneOverSinHalfAngle = 1.0f / sinHalfAngle; |
||
| 530 | blendA = (float)System.Math.Sin(halfAngle * (1.0f - blend)) * oneOverSinHalfAngle; |
||
| 531 | blendB = (float)System.Math.Sin(halfAngle * blend) * oneOverSinHalfAngle; |
||
| 532 | } |
||
| 533 | else |
||
| 534 | { |
||
| 535 | // do lerp if angle is really small. |
||
| 536 | blendA = 1.0f - blend; |
||
| 537 | blendB = blend; |
||
| 538 | } |
||
| 539 | |||
| 540 | Quaternion result = new Quaternion(blendA * q1.Xyz + blendB * q2.Xyz, blendA * q1.W + blendB * q2.W); |
||
| 541 | if (result.LengthSquared > 0.0f) |
||
| 542 | return Normalize(result); |
||
| 543 | else |
||
| 544 | return Identity; |
||
| 545 | } |
||
| 546 | |||
| 547 | #endregion |
||
| 548 | |||
| 549 | #endregion |
||
| 550 | |||
| 551 | #region Operators |
||
| 552 | |||
| 553 | /// <summary> |
||
| 554 | /// Adds two instances. |
||
| 555 | /// </summary> |
||
| 556 | /// <param name="left">The first instance.</param> |
||
| 557 | /// <param name="right">The second instance.</param> |
||
| 558 | /// <returns>The result of the calculation.</returns> |
||
| 559 | public static Quaternion operator +(Quaternion left, Quaternion right) |
||
| 560 | { |
||
| 561 | left.Xyz += right.Xyz; |
||
| 562 | left.W += right.W; |
||
| 563 | return left; |
||
| 564 | } |
||
| 565 | |||
| 566 | /// <summary> |
||
| 567 | /// Subtracts two instances. |
||
| 568 | /// </summary> |
||
| 569 | /// <param name="left">The first instance.</param> |
||
| 570 | /// <param name="right">The second instance.</param> |
||
| 571 | /// <returns>The result of the calculation.</returns> |
||
| 572 | public static Quaternion operator -(Quaternion left, Quaternion right) |
||
| 573 | { |
||
| 574 | left.Xyz -= right.Xyz; |
||
| 575 | left.W -= right.W; |
||
| 576 | return left; |
||
| 577 | } |
||
| 578 | |||
| 579 | /// <summary> |
||
| 580 | /// Multiplies two instances. |
||
| 581 | /// </summary> |
||
| 582 | /// <param name="left">The first instance.</param> |
||
| 583 | /// <param name="right">The second instance.</param> |
||
| 584 | /// <returns>The result of the calculation.</returns> |
||
| 585 | public static Quaternion operator *(Quaternion left, Quaternion right) |
||
| 586 | { |
||
| 587 | Multiply(ref left, ref right, out left); |
||
| 588 | return left; |
||
| 589 | } |
||
| 590 | |||
| 591 | /// <summary> |
||
| 592 | /// Multiplies an instance by a scalar. |
||
| 593 | /// </summary> |
||
| 594 | /// <param name="quaternion">The instance.</param> |
||
| 595 | /// <param name="scale">The scalar.</param> |
||
| 596 | /// <returns>A new instance containing the result of the calculation.</returns> |
||
| 597 | public static Quaternion operator *(Quaternion quaternion, float scale) |
||
| 598 | { |
||
| 599 | Multiply(ref quaternion, scale, out quaternion); |
||
| 600 | return quaternion; |
||
| 601 | } |
||
| 602 | |||
| 603 | /// <summary> |
||
| 604 | /// Multiplies an instance by a scalar. |
||
| 605 | /// </summary> |
||
| 606 | /// <param name="quaternion">The instance.</param> |
||
| 607 | /// <param name="scale">The scalar.</param> |
||
| 608 | /// <returns>A new instance containing the result of the calculation.</returns> |
||
| 609 | public static Quaternion operator *(float scale, Quaternion quaternion) |
||
| 610 | { |
||
| 611 | return new Quaternion(quaternion.X * scale, quaternion.Y * scale, quaternion.Z * scale, quaternion.W * scale); |
||
| 612 | } |
||
| 613 | |||
| 614 | /// <summary> |
||
| 615 | /// Compares two instances for equality. |
||
| 616 | /// </summary> |
||
| 617 | /// <param name="left">The first instance.</param> |
||
| 618 | /// <param name="right">The second instance.</param> |
||
| 619 | /// <returns>True, if left equals right; false otherwise.</returns> |
||
| 620 | public static bool operator ==(Quaternion left, Quaternion right) |
||
| 621 | { |
||
| 622 | return left.Equals(right); |
||
| 623 | } |
||
| 624 | |||
| 625 | /// <summary> |
||
| 626 | /// Compares two instances for inequality. |
||
| 627 | /// </summary> |
||
| 628 | /// <param name="left">The first instance.</param> |
||
| 629 | /// <param name="right">The second instance.</param> |
||
| 630 | /// <returns>True, if left does not equal right; false otherwise.</returns> |
||
| 631 | public static bool operator !=(Quaternion left, Quaternion right) |
||
| 632 | { |
||
| 633 | return !left.Equals(right); |
||
| 634 | } |
||
| 635 | |||
| 636 | #endregion |
||
| 637 | |||
| 638 | #region Overrides |
||
| 639 | |||
| 640 | #region public override string ToString() |
||
| 641 | |||
| 642 | /// <summary> |
||
| 643 | /// Returns a System.String that represents the current Quaternion. |
||
| 644 | /// </summary> |
||
| 645 | /// <returns></returns> |
||
| 646 | public override string ToString() |
||
| 647 | { |
||
| 648 | return String.Format("V: {0}, W: {1}", Xyz, W); |
||
| 649 | } |
||
| 650 | |||
| 651 | #endregion |
||
| 652 | |||
| 653 | #region public override bool Equals (object o) |
||
| 654 | |||
| 655 | /// <summary> |
||
| 656 | /// Compares this object instance to another object for equality. |
||
| 657 | /// </summary> |
||
| 658 | /// <param name="other">The other object to be used in the comparison.</param> |
||
| 659 | /// <returns>True if both objects are Quaternions of equal value. Otherwise it returns false.</returns> |
||
| 660 | public override bool Equals(object other) |
||
| 661 | { |
||
| 662 | if (other is Quaternion == false) return false; |
||
| 663 | return this == (Quaternion)other; |
||
| 664 | } |
||
| 665 | |||
| 666 | #endregion |
||
| 667 | |||
| 668 | #region public override int GetHashCode () |
||
| 669 | |||
| 670 | /// <summary> |
||
| 671 | /// Provides the hash code for this object. |
||
| 672 | /// </summary> |
||
| 673 | /// <returns>A hash code formed from the bitwise XOR of this objects members.</returns> |
||
| 674 | public override int GetHashCode() |
||
| 675 | { |
||
| 676 | return Xyz.GetHashCode() ^ W.GetHashCode(); |
||
| 677 | } |
||
| 678 | |||
| 679 | #endregion |
||
| 680 | |||
| 681 | #endregion |
||
| 682 | |||
| 683 | #endregion |
||
| 684 | |||
| 685 | #region IEquatable<Quaternion> Members |
||
| 686 | |||
| 687 | /// <summary> |
||
| 688 | /// Compares this Quaternion instance to another Quaternion for equality. |
||
| 689 | /// </summary> |
||
| 690 | /// <param name="other">The other Quaternion to be used in the comparison.</param> |
||
| 691 | /// <returns>True if both instances are equal; false otherwise.</returns> |
||
| 692 | public bool Equals(Quaternion other) |
||
| 693 | { |
||
| 694 | return Xyz == other.Xyz && W == other.W; |
||
| 695 | } |
||
| 696 | |||
| 697 | #endregion |
||
| 698 | } |
||
| 699 | } |