/* This program is distributed under the terms of the 'MIT license'. The text of this licence follows... Copyright (c) 2005 J.D.Medhurst (a.k.a. Tixy) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** @file @brief 3D vector maths using fixed-point arithmetic */ #ifndef __VECTOR_H__ #define __VECTOR_H__ /** @defgroup vector3 Maths - 3D Vectors @brief Routines for handling 3 dimensional points, vectors and matrices. This code is targeted at CPUs without hardware support for division or floating point. It has been optimised for ARM CPUs but should be suitable for other RISC architecures. @{ */ #include "fix.h" /** @brief A class representing a 3vector The three components of the vector; X,Y and Z, are 32bit fixed point numbers with the binary point between bits 15 and 16. @see fix Fix @version 2005-03-02 - Made Normal() faster by using integer multiplication to calculate cross product, as opposed to using fixed-point multiplication. @version 2005-03-01 - Modified Normal() so that it copes with vectors of any magnitude - by scaling the vectors prior to cross product calculation. @version 2006-05-20 - Changed code to use standard typedefs, e.g. replaced uint8 with uint8_t, and made use of size_t. */ class Vector3 { public: /** Constructor which doesn't initialise the vector object. */ inline Vector3() {} /** Constructor which initialises the vector object. @param x Value for the X component. @param y Value for the Y component. @param z Value for the Z component. */ inline Vector3(fix x,fix y,fix z) : X(x), Y(y), Z(z) {} /** Uninary minus operator. @return A vector with component values of the same magnitude as this one, but with the signs of each value reversed. */ IMPORT Vector3 operator - () const; /** Calculate the sum of this vector and another. The resulting vector is the sum of the individual component values. If any component value overflows the range of 32bit fixed point numbers, then the result is undefined. @param vector The vector to add to this. @return The sum of this and \a vector. */ IMPORT Vector3 operator + (const Vector3& vector) const; /** Calculate the difference between this vector and another. The resulting vector is the difference between the individual component values. If any component value overflows the range of 32bit fixed point numbers, then the result is undefined. @param vector The vector to subtract from this. @return The difference between this and \a vector. */ IMPORT Vector3 operator - (const Vector3& vector) const; /** Scalar multiply. The resulting vector is the product of the individual component values of this vector multiplied by the given scalar value. If any component value overflows the range of 32bit fixed point numbers, then the result is undefined. @param scalar The scalar value to multiply by. @return The product of this vector and \a scalar. */ IMPORT Vector3 operator * (fix scalar) const; /** Scalar division. The resulting vector is the result of dividing the individual component values of this vector by the given scalar value. If any component value overflows the range of 32bit fixed point numbers, then the result is undefined. @param scalar The scalar value to divide by. @return The result of dividing this vector by \a scalar. */ IMPORT Vector3 operator / (fix scalar) const; /** Add a vector to this one. The result is the sum of the individual component values. If any component value overflows the range of 32bit fixed point numbers, then the result is undefined. @param vector The vector to add to this. @return A reference to this. @post This vector is set to the calculated sum. */ IMPORT Vector3& operator += (const Vector3& vector); /** Subract a vector from this one. The result is the difference between the individual component values. If any component value overflows the range of 32bit fixed point numbers, then the result is undefined. @param vector The vector to subtract from this. @return A reference to this. @post This vector is set to the calculated difference. */ IMPORT Vector3& operator -= (const Vector3& vector); /** Scalar multiply of this vector. Multiply each component of this vector by a scalar value. If any component value overflows the range of 32bit fixed point numbers, then the result is undefined. @param scalar The scalar value to multiply by. @return A reference to this. @post This vector is result of the scalar multiply. */ IMPORT Vector3& operator *= (fix scalar); /** Scalar divide of this vector. Divide each component of this vector by a scalar value. If any component value overflows the range of 32bit fixed point numbers, then the result is undefined. @param scalar The scalar value to divide by. @return A reference to this. @post This vector is result of the scalar division. */ IMPORT Vector3& operator /= (fix scalar); /** Equality operator. @param vector The vector to test equality with. @return True, if the individual components of this vector are the same their counterparts in \a vector. False, otherwise. */ IMPORT bool operator == (const Vector3& vector) const; /** Inequality operator. @param vector The vector to test equality with. @return True, if any of individual components of this vector differ from their counterparts in \a vector. False, otherwise. */ inline bool operator != (const Vector3& vector) const { return !(*this==vector); } /** Calculate the dot product of this vector and a second vector. If any product of two components is greater than 0x2aaa.aaaa then the result is undefined. This limitation can be met if all components, in both vectors, have a magnitude less than 104. (0x68.00000) @param vector The second vector. @return The dot product of this and \a vector. */ IMPORT fix DotProduct(const Vector3& vector) const; /** Calculate the cross product of this vector and a second vector. If any product of two components is greater than 0x4000.0000 then the result is undefined. This limitation can be met if all components, in both vectors, have a magnitude less than 128. (0x80.00000) @param vector The second vector. @return The cross product of this and \a vector */ IMPORT Vector3 CrossProduct(const Vector3& vector) const; /** Calculate the length (magnitude) of this vector. Accuracy is limited to 24 significant bits. @return The length. */ IMPORT ufix Length() const; /** Compare the length (magnitude) of this vector with a given value. This is faster than comparing the value returned by Length(). E.g. instead of @code if(vector.Length() 1, if the length of this vector is greater than \a length.
-1, if the length of this vector is less than \a length. */ IMPORT int CompareLength(ufix length) const; /** Compare the length of this vector with another. This is faster than comparing two values returned by Length(). E.g. instead of @code if(vector1.Length() 1, if the length of this is greater than the length of \a vector.
-1, if the length of this is less than the length of \a vector. */ IMPORT int CompareLengths(const Vector3& vector) const; /** Calculate the square of the length of this vector. This is faster than Length() and is useful when comparing a vector length with a constant or pre-calculated value. (Comparing the square of lengths will give the same result as comparing the lengths.) @param fraction Set to the fraction part of the result, i.e the 32 bits to the right of the binary point. @return The integer part of the result. */ IMPORT uint32_t LengthSquared(uint32_t& fraction) const; /** Calculate the unit vector which lies in the same direction as this vector. I.e. scale this vector so it has a length of 1.0. Rounding inacuracies mean the length of this 'unit' vector will actualy lie in the range 0x0.fffe to 0x1.0000. @return The unit vector. */ IMPORT Vector3 UnitVector() const; /** Calculate the unit vector which is normal to this vector and a second vector. I.e. the unit vector which is at right angles to both this vector and the second vector; acording to the right-hand rule. Rounding inacuracies mean the length of this 'unit' vector will actualy lie in the range 0x0.fffe to 0x1.0000. @param vector The second vector. @return The unit vector normal to this and \a vector. */ IMPORT Vector3 Normal(const Vector3& vector) const; /** Calculate the angle between this vector and a second vector. @param vector The second vector. @return The angle between this and \a vector. This lies in the range 0x0000 and 0x8000. @see fixangle */ IMPORT fixangle Angle(const Vector3& vector) const; /** Calculate the unit vector which is normal to the two vectors formed by (\a point1 - this) and (\a point2 - this). I.e. the unit vector which is at right angles to both of these; acording to the right-hand rule. Rounding inacuracies mean the length of this 'unit' vector will actualy lie in the range 0x0.fffe to 0x1.0000. @param point1 The first point. @param point2 The second point. @return The normal vector. */ IMPORT Vector3 Normal(const Vector3& point1,const Vector3& point2) const; /** Calculate the angle between the two vectors formed by (\a point1 - this) and (\a point2 - this). @param point1 The first point. @param point2 The second point. @return The angle. This lies in the range 0x0000 and 0x8000. @see fixangle */ IMPORT fixangle Angle(const Vector3& point1,const Vector3& point2) const; /** Translate an array of vectors. I.e. add the given offset to each vector in an array. @param outVectors Pointer to array where translated vectors will be written to. @param vectorCount Number of vectors in array. @param inVectors Pointer to array vectors to be translated. @param offset The offset to add to each vector in the array. */ IMPORT static void Translate(Vector3* outVectors,unsigned vectorCount,const Vector3* inVectors,const Vector3& offset); /** Scale an array of vectors. I.e. perform a scalar multiply on each vector in an array. @param outVectors Pointer to array where scaled vectors will be written to. @param vectorCount Number of vectors in array. @param inVectors Pointer to array vectors to be scaled. @param scale The value to scale each component of each vector by. */ IMPORT static void Scale(Vector3* outVectors,unsigned vectorCount,const Vector3* inVectors,fix scale); private: /** Scale the components of this array such that the component with the largest magnitude has its most-significant bit at the given position. @param bits Bit position for MSB of largest component. */ void NormaliseComponents(unsigned bits); public: fix X; /**< The X component */ fix Y; /**< The Y component */ fix Z; /**< The Z component */ }; /** @brief A type representing a 3D point */ typedef Vector3 Point3; /** @brief A class representing a 3x3 matrix. */ class Matrix3 { public: /** Constructor which doesn't initialise the matrix object */ inline Matrix3() {} /** Constructor which initialises the matrix object using three 3vectors @param row1 Values for first row in matrix. @param row2 Values for second row in matrix. @param row3 Values for third row in matrix. */ inline Matrix3(const Vector3 row1,const Vector3 row2,const Vector3 row3) : Row1(row1), Row2(row2), Row3(row3) {} /** Multiply this matrix by a 3vector. @param vector The vector to multiply by. This is treated as a column vector. @return Result of mutiplying this matrix by \a vector */ IMPORT Vector3 operator * (const Vector3& vector) const; /** Transpose a matrix. (Exchange rows with columns.) @return The transposition of this matrix. */ IMPORT Matrix3 Transposition() const; /** Tranform an array of vectors by multiplying each against this matrix, acording to the operator*() function. @param outVectors Pointer to array where transformed vectors will be written to. @param vectorCount Number of vectors in array. @param inVectors Pointer to array vectors to be transformed. */ IMPORT void Transform(Vector3* outVectors,unsigned vectorCount,const Vector3* inVectors); public: Vector3 Row1; /**< The elements for row 1 of the matrix */ Vector3 Row2; /**< The elements for row 2 of the matrix */ Vector3 Row3; /**< The elements for row 3 of the matrix */ }; /** @} */ // End of group #endif