#region CPL License /* Nuclex Framework Copyright (C) 2002-2009 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using Microsoft.Xna.Framework; namespace Nuclex.Geometry { /// Provides helper methods for vectors public static class VectorHelper { /// Calculates the absolute values of each vector component /// Vector of which to calculate the absolute /// A new vector with the absolute value of the input vector public static Vector3 Abs(Vector3 vector) { return new Vector3( Math.Abs(vector.X), Math.Abs(vector.Y), Math.Abs(vector.Z) ); } /// Retrieves a vector component by its index /// Vector to retrieve a component of /// Index of the component to retrieve /// The value of the vector's indicated component public static float Get(ref Vector3 vector, int component) { switch(component) { case 0: { return vector.X; } case 1: { return vector.Y; } case 2: { return vector.Z; } default: { throw new ArgumentOutOfRangeException("Vector component index out of range"); } } } /// Sets a vector component by its index /// Vector to set a component of /// Index of the component to set /// Value to assign to the vector's indicated component public static void Set(ref Vector3 vector, int component, float value) { switch(component) { case 0: { vector.X = value; break; } case 1: { vector.Y = value; break; } case 2: { vector.Z = value; break; } default: { throw new ArgumentOutOfRangeException("Vector component index out of range"); } } } /// Returns a vector that is perpendicular to the input vector /// Vector to which a perpendicular vector will be found /// A vector that is perpendicular to the input vector /// /// /// This method does not care for the orientation of the resulting vector, so it /// shouldn't be used for billboards or to orient a view matrix. On the other hand, /// if you don't care for the orientation of the resulting vector, only that it is /// perpendicular, this method can provide better numerical stability and /// performance than a generic LookAt() method. /// /// /// References: /// http://www.gamedev.net/community/forums/topic.asp?topic_id=445164 /// http://www.gamedev.net/community/forums/topic.asp?topic_id=518142 /// /// public static Vector3 GetPerpendicularVector(Vector3 vector) { Vector3 result; GetPerpendicularVector(ref vector, out result); return result; } /// Returns a vector that is perpendicular to the input vector /// Vector to which a perpendicular vector will be found /// /// Output parameter that receives a vector perpendicular to the provided vector /// /// /// /// This method does not care for the orientation of the resulting vector, so it /// shouldn't be used for billboards or to orient a view matrix. On the other hand, /// if you don't care for the orientation of the resulting vector, only that it is /// perpendicular, this method can provide better numerical stability and /// performance than a generic LookAt() method. /// /// /// References: /// http://www.gamedev.net/community/forums/topic.asp?topic_id=445164 /// http://www.gamedev.net/community/forums/topic.asp?topic_id=518142 /// /// public static void GetPerpendicularVector(ref Vector3 vector, out Vector3 perpendicular) { float absX = Math.Abs(vector.X); float absY = Math.Abs(vector.Y); float absZ = Math.Abs(vector.Z); if(absX < absY) { if(absZ < absX) { perpendicular = new Vector3(vector.Y, -vector.X, 0.0f); } else { perpendicular = new Vector3(0.0f, vector.Z, -vector.Y); } } else { if(absZ < absY) { perpendicular = new Vector3(vector.Y, -vector.X, 0.0f); } else { perpendicular = new Vector3(vector.Z, 0.0f, -vector.X); } } } /// /// Builds a vector consisting of the larger absolute values from both inputs /// /// First vector to look for the larger absolute values in /// Second vector to look for the larger absolute values in /// /// A vector consisting of the larger absolute values from both input vectors /// /// /// This works similar to the Vector2.Max() method, but it will not use /// the element from the input vector that has the greater value, but look /// for the element with the greater absolute value. Thus, for the inputs /// {-10, -1} and {1, 10} it would return {-10, 10}. /// public static Vector2 AbsMax(Vector2 first, Vector2 second) { return new Vector2( (Math.Abs(first.X) >= Math.Abs(second.X)) ? first.X : second.X, (Math.Abs(first.Y) >= Math.Abs(second.Y)) ? first.Y : second.Y ); } /// /// Builds a vector consisting of the larger absolute values from both inputs /// /// First vector to look for the larger absolute values in /// Second vector to look for the larger absolute values in /// /// A vector consisting of the larger absolute values from both input vectors /// /// /// This works similar to the Vector2.Max() method, but it will not use /// the element from the input vector that has the greater value, but look /// for the element with the greater absolute value. Thus, for the inputs /// {-10, -1, 10} and {1, 10, -10} it would return {-10, 10, 10}. /// public static Vector3 AbsMax(Vector3 first, Vector3 second) { return new Vector3( (Math.Abs(first.X) >= Math.Abs(second.X)) ? first.X : second.X, (Math.Abs(first.Y) >= Math.Abs(second.Y)) ? first.Y : second.Y, (Math.Abs(first.Z) >= Math.Abs(second.Z)) ? first.Z : second.Z ); } } } // namespace Nuclex.Geometry