Viewing file: ImathVec.h (44.17 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004-2012, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMATHVEC_H #define INCLUDED_IMATHVEC_H
//---------------------------------------------------- // // 2D, 3D and 4D point/vector class templates // //----------------------------------------------------
#include "ImathExc.h" #include "ImathLimits.h" #include "ImathMath.h" #include "ImathNamespace.h"
#include <iostream>
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER // suppress exception specification warnings #pragma warning(push) #pragma warning(disable:4290) #endif
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
template <class T> class Vec2; template <class T> class Vec3; template <class T> class Vec4;
enum InfException {INF_EXCEPTION};
template <class T> class Vec2 { public:
//------------------- // Access to elements //-------------------
T x, y;
T & operator [] (int i); const T & operator [] (int i) const;
//------------- // Constructors //-------------
Vec2 (); // no initialization explicit Vec2 (T a); // (a a) Vec2 (T a, T b); // (a b)
//--------------------------------- // Copy constructors and assignment //---------------------------------
Vec2 (const Vec2 &v); template <class S> Vec2 (const Vec2<S> &v);
const Vec2 & operator = (const Vec2 &v);
//---------------------- // Compatibility with Sb //----------------------
template <class S> void setValue (S a, S b);
template <class S> void setValue (const Vec2<S> &v);
template <class S> void getValue (S &a, S &b) const;
template <class S> void getValue (Vec2<S> &v) const;
T * getValue (); const T * getValue () const;
//--------- // Equality //---------
template <class S> bool operator == (const Vec2<S> &v) const;
template <class S> bool operator != (const Vec2<S> &v) const;
//----------------------------------------------------------------------- // Compare two vectors and test if they are "approximately equal": // // equalWithAbsError (v, e) // // Returns true if the coefficients of this and v are the same with // an absolute error of no more than e, i.e., for all i // // abs (this[i] - v[i]) <= e // // equalWithRelError (v, e) // // Returns true if the coefficients of this and v are the same with // a relative error of no more than e, i.e., for all i // // abs (this[i] - v[i]) <= e * abs (this[i]) //-----------------------------------------------------------------------
bool equalWithAbsError (const Vec2<T> &v, T e) const; bool equalWithRelError (const Vec2<T> &v, T e) const;
//------------ // Dot product //------------
T dot (const Vec2 &v) const; T operator ^ (const Vec2 &v) const;
//------------------------------------------------ // Right-handed cross product, i.e. z component of // Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0) //------------------------------------------------
T cross (const Vec2 &v) const; T operator % (const Vec2 &v) const;
//------------------------ // Component-wise addition //------------------------
const Vec2 & operator += (const Vec2 &v); Vec2 operator + (const Vec2 &v) const;
//--------------------------- // Component-wise subtraction //---------------------------
const Vec2 & operator -= (const Vec2 &v); Vec2 operator - (const Vec2 &v) const;
//------------------------------------ // Component-wise multiplication by -1 //------------------------------------
Vec2 operator - () const; const Vec2 & negate ();
//------------------------------ // Component-wise multiplication //------------------------------
const Vec2 & operator *= (const Vec2 &v); const Vec2 & operator *= (T a); Vec2 operator * (const Vec2 &v) const; Vec2 operator * (T a) const;
//------------------------ // Component-wise division //------------------------
const Vec2 & operator /= (const Vec2 &v); const Vec2 & operator /= (T a); Vec2 operator / (const Vec2 &v) const; Vec2 operator / (T a) const;
//---------------------------------------------------------------- // Length and normalization: If v.length() is 0.0, v.normalize() // and v.normalized() produce a null vector; v.normalizeExc() and // v.normalizedExc() throw a NullVecExc. // v.normalizeNonNull() and v.normalizedNonNull() are slightly // faster than the other normalization routines, but if v.length() // is 0.0, the result is undefined. //----------------------------------------------------------------
T length () const; T length2 () const;
const Vec2 & normalize (); // modifies *this const Vec2 & normalizeExc () throw (IEX_NAMESPACE::MathExc); const Vec2 & normalizeNonNull ();
Vec2<T> normalized () const; // does not modify *this Vec2<T> normalizedExc () const throw (IEX_NAMESPACE::MathExc); Vec2<T> normalizedNonNull () const;
//-------------------------------------------------------- // Number of dimensions, i.e. number of elements in a Vec2 //--------------------------------------------------------
static unsigned int dimensions() {return 2;}
//------------------------------------------------- // Limitations of type T (see also class limits<T>) //-------------------------------------------------
static T baseTypeMin() {return limits<T>::min();} static T baseTypeMax() {return limits<T>::max();} static T baseTypeSmallest() {return limits<T>::smallest();} static T baseTypeEpsilon() {return limits<T>::epsilon();}
//-------------------------------------------------------------- // Base type -- in templates, which accept a parameter, V, which // could be either a Vec2<T>, a Vec3<T>, or a Vec4<T> you can // refer to T as V::BaseType //--------------------------------------------------------------
typedef T BaseType;
private:
T lengthTiny () const; };
template <class T> class Vec3 { public:
//------------------- // Access to elements //-------------------
T x, y, z;
T & operator [] (int i); const T & operator [] (int i) const;
//------------- // Constructors //-------------
Vec3 (); // no initialization explicit Vec3 (T a); // (a a a) Vec3 (T a, T b, T c); // (a b c)
//--------------------------------- // Copy constructors and assignment //---------------------------------
Vec3 (const Vec3 &v); template <class S> Vec3 (const Vec3<S> &v);
const Vec3 & operator = (const Vec3 &v);
//--------------------------------------------------------- // Vec4 to Vec3 conversion, divides x, y and z by w: // // The one-argument conversion function divides by w even // if w is zero. The result depends on how the environment // handles floating-point exceptions. // // The two-argument version thows an InfPointExc exception // if w is zero or if division by w would overflow. //---------------------------------------------------------
template <class S> explicit Vec3 (const Vec4<S> &v); template <class S> explicit Vec3 (const Vec4<S> &v, InfException);
//---------------------- // Compatibility with Sb //----------------------
template <class S> void setValue (S a, S b, S c);
template <class S> void setValue (const Vec3<S> &v);
template <class S> void getValue (S &a, S &b, S &c) const;
template <class S> void getValue (Vec3<S> &v) const;
T * getValue(); const T * getValue() const;
//--------- // Equality //---------
template <class S> bool operator == (const Vec3<S> &v) const;
template <class S> bool operator != (const Vec3<S> &v) const;
//----------------------------------------------------------------------- // Compare two vectors and test if they are "approximately equal": // // equalWithAbsError (v, e) // // Returns true if the coefficients of this and v are the same with // an absolute error of no more than e, i.e., for all i // // abs (this[i] - v[i]) <= e // // equalWithRelError (v, e) // // Returns true if the coefficients of this and v are the same with // a relative error of no more than e, i.e., for all i // // abs (this[i] - v[i]) <= e * abs (this[i]) //-----------------------------------------------------------------------
bool equalWithAbsError (const Vec3<T> &v, T e) const; bool equalWithRelError (const Vec3<T> &v, T e) const;
//------------ // Dot product //------------
T dot (const Vec3 &v) const; T operator ^ (const Vec3 &v) const;
//--------------------------- // Right-handed cross product //---------------------------
Vec3 cross (const Vec3 &v) const; const Vec3 & operator %= (const Vec3 &v); Vec3 operator % (const Vec3 &v) const;
//------------------------ // Component-wise addition //------------------------
const Vec3 & operator += (const Vec3 &v); Vec3 operator + (const Vec3 &v) const;
//--------------------------- // Component-wise subtraction //---------------------------
const Vec3 & operator -= (const Vec3 &v); Vec3 operator - (const Vec3 &v) const;
//------------------------------------ // Component-wise multiplication by -1 //------------------------------------
Vec3 operator - () const; const Vec3 & negate ();
//------------------------------ // Component-wise multiplication //------------------------------
const Vec3 & operator *= (const Vec3 &v); const Vec3 & operator *= (T a); Vec3 operator * (const Vec3 &v) const; Vec3 operator * (T a) const;
//------------------------ // Component-wise division //------------------------
const Vec3 & operator /= (const Vec3 &v); const Vec3 & operator /= (T a); Vec3 operator / (const Vec3 &v) const; Vec3 operator / (T a) const;
//---------------------------------------------------------------- // Length and normalization: If v.length() is 0.0, v.normalize() // and v.normalized() produce a null vector; v.normalizeExc() and // v.normalizedExc() throw a NullVecExc. // v.normalizeNonNull() and v.normalizedNonNull() are slightly // faster than the other normalization routines, but if v.length() // is 0.0, the result is undefined. //----------------------------------------------------------------
T length () const; T length2 () const;
const Vec3 & normalize (); // modifies *this const Vec3 & normalizeExc () throw (IEX_NAMESPACE::MathExc); const Vec3 & normalizeNonNull ();
Vec3<T> normalized () const; // does not modify *this Vec3<T> normalizedExc () const throw (IEX_NAMESPACE::MathExc); Vec3<T> normalizedNonNull () const;
//-------------------------------------------------------- // Number of dimensions, i.e. number of elements in a Vec3 //--------------------------------------------------------
static unsigned int dimensions() {return 3;}
//------------------------------------------------- // Limitations of type T (see also class limits<T>) //-------------------------------------------------
static T baseTypeMin() {return limits<T>::min();} static T baseTypeMax() {return limits<T>::max();} static T baseTypeSmallest() {return limits<T>::smallest();} static T baseTypeEpsilon() {return limits<T>::epsilon();}
//-------------------------------------------------------------- // Base type -- in templates, which accept a parameter, V, which // could be either a Vec2<T>, a Vec3<T>, or a Vec4<T> you can // refer to T as V::BaseType //--------------------------------------------------------------
typedef T BaseType;
private:
T lengthTiny () const; };
template <class T> class Vec4 { public:
//------------------- // Access to elements //-------------------
T x, y, z, w;
T & operator [] (int i); const T & operator [] (int i) const;
//------------- // Constructors //-------------
Vec4 (); // no initialization explicit Vec4 (T a); // (a a a a) Vec4 (T a, T b, T c, T d); // (a b c d)
//--------------------------------- // Copy constructors and assignment //---------------------------------
Vec4 (const Vec4 &v); template <class S> Vec4 (const Vec4<S> &v);
const Vec4 & operator = (const Vec4 &v);
//------------------------------------- // Vec3 to Vec4 conversion, sets w to 1 //-------------------------------------
template <class S> explicit Vec4 (const Vec3<S> &v);
//--------- // Equality //---------
template <class S> bool operator == (const Vec4<S> &v) const;
template <class S> bool operator != (const Vec4<S> &v) const;
//----------------------------------------------------------------------- // Compare two vectors and test if they are "approximately equal": // // equalWithAbsError (v, e) // // Returns true if the coefficients of this and v are the same with // an absolute error of no more than e, i.e., for all i // // abs (this[i] - v[i]) <= e // // equalWithRelError (v, e) // // Returns true if the coefficients of this and v are the same with // a relative error of no more than e, i.e., for all i // // abs (this[i] - v[i]) <= e * abs (this[i]) //-----------------------------------------------------------------------
bool equalWithAbsError (const Vec4<T> &v, T e) const; bool equalWithRelError (const Vec4<T> &v, T e) const;
//------------ // Dot product //------------
T dot (const Vec4 &v) const; T operator ^ (const Vec4 &v) const;
//----------------------------------- // Cross product is not defined in 4D //-----------------------------------
//------------------------ // Component-wise addition //------------------------
const Vec4 & operator += (const Vec4 &v); Vec4 operator + (const Vec4 &v) const;
//--------------------------- // Component-wise subtraction //---------------------------
const Vec4 & operator -= (const Vec4 &v); Vec4 operator - (const Vec4 &v) const;
//------------------------------------ // Component-wise multiplication by -1 //------------------------------------
Vec4 operator - () const; const Vec4 & negate ();
//------------------------------ // Component-wise multiplication //------------------------------
const Vec4 & operator *= (const Vec4 &v); const Vec4 & operator *= (T a); Vec4 operator * (const Vec4 &v) const; Vec4 operator * (T a) const;
//------------------------ // Component-wise division //------------------------
const Vec4 & operator /= (const Vec4 &v); const Vec4 & operator /= (T a); Vec4 operator / (const Vec4 &v) const; Vec4 operator / (T a) const;
//---------------------------------------------------------------- // Length and normalization: If v.length() is 0.0, v.normalize() // and v.normalized() produce a null vector; v.normalizeExc() and // v.normalizedExc() throw a NullVecExc. // v.normalizeNonNull() and v.normalizedNonNull() are slightly // faster than the other normalization routines, but if v.length() // is 0.0, the result is undefined. //----------------------------------------------------------------
T length () const; T length2 () const;
const Vec4 & normalize (); // modifies *this const Vec4 & normalizeExc () throw (IEX_NAMESPACE::MathExc); const Vec4 & normalizeNonNull ();
Vec4<T> normalized () const; // does not modify *this Vec4<T> normalizedExc () const throw (IEX_NAMESPACE::MathExc); Vec4<T> normalizedNonNull () const;
//-------------------------------------------------------- // Number of dimensions, i.e. number of elements in a Vec4 //--------------------------------------------------------
static unsigned int dimensions() {return 4;}
//------------------------------------------------- // Limitations of type T (see also class limits<T>) //-------------------------------------------------
static T baseTypeMin() {return limits<T>::min();} static T baseTypeMax() {return limits<T>::max();} static T baseTypeSmallest() {return limits<T>::smallest();} static T baseTypeEpsilon() {return limits<T>::epsilon();}
//-------------------------------------------------------------- // Base type -- in templates, which accept a parameter, V, which // could be either a Vec2<T>, a Vec3<T>, or a Vec4<T> you can // refer to T as V::BaseType //--------------------------------------------------------------
typedef T BaseType;
private:
T lengthTiny () const; };
//-------------- // Stream output //--------------
template <class T> std::ostream & operator << (std::ostream &s, const Vec2<T> &v);
template <class T> std::ostream & operator << (std::ostream &s, const Vec3<T> &v);
template <class T> std::ostream & operator << (std::ostream &s, const Vec4<T> &v);
//---------------------------------------------------- // Reverse multiplication: S * Vec2<T> and S * Vec3<T> //----------------------------------------------------
template <class T> Vec2<T> operator * (T a, const Vec2<T> &v); template <class T> Vec3<T> operator * (T a, const Vec3<T> &v); template <class T> Vec4<T> operator * (T a, const Vec4<T> &v);
//------------------------- // Typedefs for convenience //-------------------------
typedef Vec2 <short> V2s; typedef Vec2 <int> V2i; typedef Vec2 <float> V2f; typedef Vec2 <double> V2d; typedef Vec3 <short> V3s; typedef Vec3 <int> V3i; typedef Vec3 <float> V3f; typedef Vec3 <double> V3d; typedef Vec4 <short> V4s; typedef Vec4 <int> V4i; typedef Vec4 <float> V4f; typedef Vec4 <double> V4d;
//------------------------------------------- // Specializations for VecN<short>, VecN<int> //-------------------------------------------
// Vec2<short>
template <> short Vec2<short>::length () const;
template <> const Vec2<short> & Vec2<short>::normalize ();
template <> const Vec2<short> & Vec2<short>::normalizeExc () throw (IEX_NAMESPACE::MathExc);
template <> const Vec2<short> & Vec2<short>::normalizeNonNull ();
template <> Vec2<short> Vec2<short>::normalized () const;
template <> Vec2<short> Vec2<short>::normalizedExc () const throw (IEX_NAMESPACE::MathExc);
template <> Vec2<short> Vec2<short>::normalizedNonNull () const;
// Vec2<int>
template <> int Vec2<int>::length () const;
template <> const Vec2<int> & Vec2<int>::normalize ();
template <> const Vec2<int> & Vec2<int>::normalizeExc () throw (IEX_NAMESPACE::MathExc);
template <> const Vec2<int> & Vec2<int>::normalizeNonNull ();
template <> Vec2<int> Vec2<int>::normalized () const;
template <> Vec2<int> Vec2<int>::normalizedExc () const throw (IEX_NAMESPACE::MathExc);
template <> Vec2<int> Vec2<int>::normalizedNonNull () const;
// Vec3<short>
template <> short Vec3<short>::length () const;
template <> const Vec3<short> & Vec3<short>::normalize ();
template <> const Vec3<short> & Vec3<short>::normalizeExc () throw (IEX_NAMESPACE::MathExc);
template <> const Vec3<short> & Vec3<short>::normalizeNonNull ();
template <> Vec3<short> Vec3<short>::normalized () const;
template <> Vec3<short> Vec3<short>::normalizedExc () const throw (IEX_NAMESPACE::MathExc);
template <> Vec3<short> Vec3<short>::normalizedNonNull () const;
// Vec3<int>
template <> int Vec3<int>::length () const;
template <> const Vec3<int> & Vec3<int>::normalize ();
template <> const Vec3<int> & Vec3<int>::normalizeExc () throw (IEX_NAMESPACE::MathExc);
template <> const Vec3<int> & Vec3<int>::normalizeNonNull ();
template <> Vec3<int> Vec3<int>::normalized () const;
template <> Vec3<int> Vec3<int>::normalizedExc () const throw (IEX_NAMESPACE::MathExc);
template <> Vec3<int> Vec3<int>::normalizedNonNull () const;
// Vec4<short>
template <> short Vec4<short>::length () const;
template <> const Vec4<short> & Vec4<short>::normalize ();
template <> const Vec4<short> & Vec4<short>::normalizeExc () throw (IEX_NAMESPACE::MathExc);
template <> const Vec4<short> & Vec4<short>::normalizeNonNull ();
template <> Vec4<short> Vec4<short>::normalized () const;
template <> Vec4<short> Vec4<short>::normalizedExc () const throw (IEX_NAMESPACE::MathExc);
template <> Vec4<short> Vec4<short>::normalizedNonNull () const;
// Vec4<int>
template <> int Vec4<int>::length () const;
template <> const Vec4<int> & Vec4<int>::normalize ();
template <> const Vec4<int> & Vec4<int>::normalizeExc () throw (IEX_NAMESPACE::MathExc);
template <> const Vec4<int> & Vec4<int>::normalizeNonNull ();
template <> Vec4<int> Vec4<int>::normalized () const;
template <> Vec4<int> Vec4<int>::normalizedExc () const throw (IEX_NAMESPACE::MathExc);
template <> Vec4<int> Vec4<int>::normalizedNonNull () const;
//------------------------ // Implementation of Vec2: //------------------------
template <class T> inline T & Vec2<T>::operator [] (int i) { return (&x)[i]; }
template <class T> inline const T & Vec2<T>::operator [] (int i) const { return (&x)[i]; }
template <class T> inline Vec2<T>::Vec2 () { // empty }
template <class T> inline Vec2<T>::Vec2 (T a) { x = y = a; }
template <class T> inline Vec2<T>::Vec2 (T a, T b) { x = a; y = b; }
template <class T> inline Vec2<T>::Vec2 (const Vec2 &v) { x = v.x; y = v.y; }
template <class T> template <class S> inline Vec2<T>::Vec2 (const Vec2<S> &v) { x = T (v.x); y = T (v.y); }
template <class T> inline const Vec2<T> & Vec2<T>::operator = (const Vec2 &v) { x = v.x; y = v.y; return *this; }
template <class T> template <class S> inline void Vec2<T>::setValue (S a, S b) { x = T (a); y = T (b); }
template <class T> template <class S> inline void Vec2<T>::setValue (const Vec2<S> &v) { x = T (v.x); y = T (v.y); }
template <class T> template <class S> inline void Vec2<T>::getValue (S &a, S &b) const { a = S (x); b = S (y); }
template <class T> template <class S> inline void Vec2<T>::getValue (Vec2<S> &v) const { v.x = S (x); v.y = S (y); }
template <class T> inline T * Vec2<T>::getValue() { return (T *) &x; }
template <class T> inline const T * Vec2<T>::getValue() const { return (const T *) &x; }
template <class T> template <class S> inline bool Vec2<T>::operator == (const Vec2<S> &v) const { return x == v.x && y == v.y; }
template <class T> template <class S> inline bool Vec2<T>::operator != (const Vec2<S> &v) const { return x != v.x || y != v.y; }
template <class T> bool Vec2<T>::equalWithAbsError (const Vec2<T> &v, T e) const { for (int i = 0; i < 2; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) return false;
return true; }
template <class T> bool Vec2<T>::equalWithRelError (const Vec2<T> &v, T e) const { for (int i = 0; i < 2; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) return false;
return true; }
template <class T> inline T Vec2<T>::dot (const Vec2 &v) const { return x * v.x + y * v.y; }
template <class T> inline T Vec2<T>::operator ^ (const Vec2 &v) const { return dot (v); }
template <class T> inline T Vec2<T>::cross (const Vec2 &v) const { return x * v.y - y * v.x;
}
template <class T> inline T Vec2<T>::operator % (const Vec2 &v) const { return x * v.y - y * v.x; }
template <class T> inline const Vec2<T> & Vec2<T>::operator += (const Vec2 &v) { x += v.x; y += v.y; return *this; }
template <class T> inline Vec2<T> Vec2<T>::operator + (const Vec2 &v) const { return Vec2 (x + v.x, y + v.y); }
template <class T> inline const Vec2<T> & Vec2<T>::operator -= (const Vec2 &v) { x -= v.x; y -= v.y; return *this; }
template <class T> inline Vec2<T> Vec2<T>::operator - (const Vec2 &v) const { return Vec2 (x - v.x, y - v.y); }
template <class T> inline Vec2<T> Vec2<T>::operator - () const { return Vec2 (-x, -y); }
template <class T> inline const Vec2<T> & Vec2<T>::negate () { x = -x; y = -y; return *this; }
template <class T> inline const Vec2<T> & Vec2<T>::operator *= (const Vec2 &v) { x *= v.x; y *= v.y; return *this; }
template <class T> inline const Vec2<T> & Vec2<T>::operator *= (T a) { x *= a; y *= a; return *this; }
template <class T> inline Vec2<T> Vec2<T>::operator * (const Vec2 &v) const { return Vec2 (x * v.x, y * v.y); }
template <class T> inline Vec2<T> Vec2<T>::operator * (T a) const { return Vec2 (x * a, y * a); }
template <class T> inline const Vec2<T> & Vec2<T>::operator /= (const Vec2 &v) { x /= v.x; y /= v.y; return *this; }
template <class T> inline const Vec2<T> & Vec2<T>::operator /= (T a) { x /= a; y /= a; return *this; }
template <class T> inline Vec2<T> Vec2<T>::operator / (const Vec2 &v) const { return Vec2 (x / v.x, y / v.y); }
template <class T> inline Vec2<T> Vec2<T>::operator / (T a) const { return Vec2 (x / a, y / a); }
template <class T> T Vec2<T>::lengthTiny () const { T absX = (x >= T (0))? x: -x; T absY = (y >= T (0))? y: -y; T max = absX;
if (max < absY) max = absY;
if (max == T (0)) return T (0);
// // Do not replace the divisions by max with multiplications by 1/max. // Computing 1/max can overflow but the divisions below will always // produce results less than or equal to 1. //
absX /= max; absY /= max;
return max * Math<T>::sqrt (absX * absX + absY * absY); }
template <class T> inline T Vec2<T>::length () const { T length2 = dot (*this);
if (length2 < T (2) * limits<T>::smallest()) return lengthTiny();
return Math<T>::sqrt (length2); }
template <class T> inline T Vec2<T>::length2 () const { return dot (*this); }
template <class T> const Vec2<T> & Vec2<T>::normalize () { T l = length();
if (l != T (0)) { // // Do not replace the divisions by l with multiplications by 1/l. // Computing 1/l can overflow but the divisions below will always // produce results less than or equal to 1. //
x /= l; y /= l; }
return *this; }
template <class T> const Vec2<T> & Vec2<T>::normalizeExc () throw (IEX_NAMESPACE::MathExc) { T l = length();
if (l == T (0)) throw NullVecExc ("Cannot normalize null vector.");
x /= l; y /= l; return *this; }
template <class T> inline const Vec2<T> & Vec2<T>::normalizeNonNull () { T l = length(); x /= l; y /= l; return *this; }
template <class T> Vec2<T> Vec2<T>::normalized () const { T l = length();
if (l == T (0)) return Vec2 (T (0));
return Vec2 (x / l, y / l); }
template <class T> Vec2<T> Vec2<T>::normalizedExc () const throw (IEX_NAMESPACE::MathExc) { T l = length();
if (l == T (0)) throw NullVecExc ("Cannot normalize null vector.");
return Vec2 (x / l, y / l); }
template <class T> inline Vec2<T> Vec2<T>::normalizedNonNull () const { T l = length(); return Vec2 (x / l, y / l); }
//----------------------- // Implementation of Vec3 //-----------------------
template <class T> inline T & Vec3<T>::operator [] (int i) { return (&x)[i]; }
template <class T> inline const T & Vec3<T>::operator [] (int i) const { return (&x)[i]; }
template <class T> inline Vec3<T>::Vec3 () { // empty }
template <class T> inline Vec3<T>::Vec3 (T a) { x = y = z = a; }
template <class T> inline Vec3<T>::Vec3 (T a, T b, T c) { x = a; y = b; z = c; }
template <class T> inline Vec3<T>::Vec3 (const Vec3 &v) { x = v.x; y = v.y; z = v.z; }
template <class T> template <class S> inline Vec3<T>::Vec3 (const Vec3<S> &v) { x = T (v.x); y = T (v.y); z = T (v.z); }
template <class T> inline const Vec3<T> & Vec3<T>::operator = (const Vec3 &v) { x = v.x; y = v.y; z = v.z; return *this; }
template <class T> template <class S> inline Vec3<T>::Vec3 (const Vec4<S> &v) { x = T (v.x / v.w); y = T (v.y / v.w); z = T (v.z / v.w); }
template <class T> template <class S> Vec3<T>::Vec3 (const Vec4<S> &v, InfException) { T vx = T (v.x); T vy = T (v.y); T vz = T (v.z); T vw = T (v.w);
T absW = (vw >= T (0))? vw: -vw;
if (absW < 1) { T m = baseTypeMax() * absW; if (vx <= -m || vx >= m || vy <= -m || vy >= m || vz <= -m || vz >= m) throw InfPointExc ("Cannot normalize point at infinity."); }
x = vx / vw; y = vy / vw; z = vz / vw; }
template <class T> template <class S> inline void Vec3<T>::setValue (S a, S b, S c) { x = T (a); y = T (b); z = T (c); }
template <class T> template <class S> inline void Vec3<T>::setValue (const Vec3<S> &v) { x = T (v.x); y = T (v.y); z = T (v.z); }
template <class T> template <class S> inline void Vec3<T>::getValue (S &a, S &b, S &c) const { a = S (x); b = S (y); c = S (z); }
template <class T> template <class S> inline void Vec3<T>::getValue (Vec3<S> &v) const { v.x = S (x); v.y = S (y); v.z = S (z); }
template <class T> inline T * Vec3<T>::getValue() { return (T *) &x; }
template <class T> inline const T * Vec3<T>::getValue() const { return (const T *) &x; }
template <class T> template <class S> inline bool Vec3<T>::operator == (const Vec3<S> &v) const { return x == v.x && y == v.y && z == v.z; }
template <class T> template <class S> inline bool Vec3<T>::operator != (const Vec3<S> &v) const { return x != v.x || y != v.y || z != v.z; }
template <class T> bool Vec3<T>::equalWithAbsError (const Vec3<T> &v, T e) const { for (int i = 0; i < 3; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) return false;
return true; }
template <class T> bool Vec3<T>::equalWithRelError (const Vec3<T> &v, T e) const { for (int i = 0; i < 3; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) return false;
return true; }
template <class T> inline T Vec3<T>::dot (const Vec3 &v) const { return x * v.x + y * v.y + z * v.z; }
template <class T> inline T Vec3<T>::operator ^ (const Vec3 &v) const { return dot (v); }
template <class T> inline Vec3<T> Vec3<T>::cross (const Vec3 &v) const { return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); }
template <class T> inline const Vec3<T> & Vec3<T>::operator %= (const Vec3 &v) { T a = y * v.z - z * v.y; T b = z * v.x - x * v.z; T c = x * v.y - y * v.x; x = a; y = b; z = c; return *this; }
template <class T> inline Vec3<T> Vec3<T>::operator % (const Vec3 &v) const { return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); }
template <class T> inline const Vec3<T> & Vec3<T>::operator += (const Vec3 &v) { x += v.x; y += v.y; z += v.z; return *this; }
template <class T> inline Vec3<T> Vec3<T>::operator + (const Vec3 &v) const { return Vec3 (x + v.x, y + v.y, z + v.z); }
template <class T> inline const Vec3<T> & Vec3<T>::operator -= (const Vec3 &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
template <class T> inline Vec3<T> Vec3<T>::operator - (const Vec3 &v) const { return Vec3 (x - v.x, y - v.y, z - v.z); }
template <class T> inline Vec3<T> Vec3<T>::operator - () const { return Vec3 (-x, -y, -z); }
template <class T> inline const Vec3<T> & Vec3<T>::negate () { x = -x; y = -y; z = -z; return *this; }
template <class T> inline const Vec3<T> & Vec3<T>::operator *= (const Vec3 &v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
template <class T> inline const Vec3<T> & Vec3<T>::operator *= (T a) { x *= a; y *= a; z *= a; return *this; }
template <class T> inline Vec3<T> Vec3<T>::operator * (const Vec3 &v) const { return Vec3 (x * v.x, y * v.y, z * v.z); }
template <class T> inline Vec3<T> Vec3<T>::operator * (T a) const { return Vec3 (x * a, y * a, z * a); }
template <class T> inline const Vec3<T> & Vec3<T>::operator /= (const Vec3 &v) { x /= v.x; y /= v.y; z /= v.z; return *this; }
template <class T> inline const Vec3<T> & Vec3<T>::operator /= (T a) { x /= a; y /= a; z /= a; return *this; }
template <class T> inline Vec3<T> Vec3<T>::operator / (const Vec3 &v) const { return Vec3 (x / v.x, y / v.y, z / v.z); }
template <class T> inline Vec3<T> Vec3<T>::operator / (T a) const { return Vec3 (x / a, y / a, z / a); }
template <class T> T Vec3<T>::lengthTiny () const { T absX = (x >= T (0))? x: -x; T absY = (y >= T (0))? y: -y; T absZ = (z >= T (0))? z: -z; T max = absX;
if (max < absY) max = absY;
if (max < absZ) max = absZ;
if (max == T (0)) return T (0);
// // Do not replace the divisions by max with multiplications by 1/max. // Computing 1/max can overflow but the divisions below will always // produce results less than or equal to 1. //
absX /= max; absY /= max; absZ /= max;
return max * Math<T>::sqrt (absX * absX + absY * absY + absZ * absZ); }
template <class T> inline T Vec3<T>::length () const { T length2 = dot (*this);
if (length2 < T (2) * limits<T>::smallest()) return lengthTiny();
return Math<T>::sqrt (length2); }
template <class T> inline T Vec3<T>::length2 () const { return dot (*this); }
template <class T> const Vec3<T> & Vec3<T>::normalize () { T l = length();
if (l != T (0)) { // // Do not replace the divisions by l with multiplications by 1/l. // Computing 1/l can overflow but the divisions below will always // produce results less than or equal to 1. //
x /= l; y /= l; z /= l; }
return *this; }
template <class T> const Vec3<T> & Vec3<T>::normalizeExc () throw (IEX_NAMESPACE::MathExc) { T l = length();
if (l == T (0)) throw NullVecExc ("Cannot normalize null vector.");
x /= l; y /= l; z /= l; return *this; }
template <class T> inline const Vec3<T> & Vec3<T>::normalizeNonNull () { T l = length(); x /= l; y /= l; z /= l; return *this; }
template <class T> Vec3<T> Vec3<T>::normalized () const { T l = length();
if (l == T (0)) return Vec3 (T (0));
return Vec3 (x / l, y / l, z / l); }
template <class T> Vec3<T> Vec3<T>::normalizedExc () const throw (IEX_NAMESPACE::MathExc) { T l = length();
if (l == T (0)) throw NullVecExc ("Cannot normalize null vector.");
return Vec3 (x / l, y / l, z / l); }
template <class T> inline Vec3<T> Vec3<T>::normalizedNonNull () const { T l = length(); return Vec3 (x / l, y / l, z / l); }
//----------------------- // Implementation of Vec4 //-----------------------
template <class T> inline T & Vec4<T>::operator [] (int i) { return (&x)[i]; }
template <class T> inline const T & Vec4<T>::operator [] (int i) const { return (&x)[i]; }
template <class T> inline Vec4<T>::Vec4 () { // empty }
template <class T> inline Vec4<T>::Vec4 (T a) { x = y = z = w = a; }
template <class T> inline Vec4<T>::Vec4 (T a, T b, T c, T d) { x = a; y = b; z = c; w = d; }
template <class T> inline Vec4<T>::Vec4 (const Vec4 &v) { x = v.x; y = v.y; z = v.z; w = v.w; }
template <class T> template <class S> inline Vec4<T>::Vec4 (const Vec4<S> &v) { x = T (v.x); y = T (v.y); z = T (v.z); w = T (v.w); }
template <class T> inline const Vec4<T> & Vec4<T>::operator = (const Vec4 &v) { x = v.x; y = v.y; z = v.z; w = v.w; return *this; }
template <class T> template <class S> inline Vec4<T>::Vec4 (const Vec3<S> &v) { x = T (v.x); y = T (v.y); z = T (v.z); w = T (1); }
template <class T> template <class S> inline bool Vec4<T>::operator == (const Vec4<S> &v) const { return x == v.x && y == v.y && z == v.z && w == v.w; }
template <class T> template <class S> inline bool Vec4<T>::operator != (const Vec4<S> &v) const { return x != v.x || y != v.y || z != v.z || w != v.w; }
template <class T> bool Vec4<T>::equalWithAbsError (const Vec4<T> &v, T e) const { for (int i = 0; i < 4; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) return false;
return true; }
template <class T> bool Vec4<T>::equalWithRelError (const Vec4<T> &v, T e) const { for (int i = 0; i < 4; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) return false;
return true; }
template <class T> inline T Vec4<T>::dot (const Vec4 &v) const { return x * v.x + y * v.y + z * v.z + w * v.w; }
template <class T> inline T Vec4<T>::operator ^ (const Vec4 &v) const { return dot (v); }
template <class T> inline const Vec4<T> & Vec4<T>::operator += (const Vec4 &v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
template <class T> inline Vec4<T> Vec4<T>::operator + (const Vec4 &v) const { return Vec4 (x + v.x, y + v.y, z + v.z, w + v.w); }
template <class T> inline const Vec4<T> & Vec4<T>::operator -= (const Vec4 &v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
template <class T> inline Vec4<T> Vec4<T>::operator - (const Vec4 &v) const { return Vec4 (x - v.x, y - v.y, z - v.z, w - v.w); }
template <class T> inline Vec4<T> Vec4<T>::operator - () const { return Vec4 (-x, -y, -z, -w); }
template <class T> inline const Vec4<T> & Vec4<T>::negate () { x = -x; y = -y; z = -z; w = -w; return *this; }
template <class T> inline const Vec4<T> & Vec4<T>::operator *= (const Vec4 &v) { x *= v.x; y *= v.y; z *= v.z; w *= v.w; return *this; }
template <class T> inline const Vec4<T> & Vec4<T>::operator *= (T a) { x *= a; y *= a; z *= a; w *= a; return *this; }
template <class T> inline Vec4<T> Vec4<T>::operator * (const Vec4 &v) const { return Vec4 (x * v.x, y * v.y, z * v.z, w * v.w); }
template <class T> inline Vec4<T> Vec4<T>::operator * (T a) const { return Vec4 (x * a, y * a, z * a, w * a); }
template <class T> inline const Vec4<T> & Vec4<T>::operator /= (const Vec4 &v) { x /= v.x; y /= v.y; z /= v.z; w /= v.w; return *this; }
template <class T> inline const Vec4<T> & Vec4<T>::operator /= (T a) { x /= a; y /= a; z /= a; w /= a; return *this; }
template <class T> inline Vec4<T> Vec4<T>::operator / (const Vec4 &v) const { return Vec4 (x / v.x, y / v.y, z / v.z, w / v.w); }
template <class T> inline Vec4<T> Vec4<T>::operator / (T a) const { return Vec4 (x / a, y / a, z / a, w / a); }
template <class T> T Vec4<T>::lengthTiny () const { T absX = (x >= T (0))? x: -x; T absY = (y >= T (0))? y: -y; T absZ = (z >= T (0))? z: -z; T absW = (w >= T (0))? w: -w; T max = absX;
if (max < absY) max = absY;
if (max < absZ) max = absZ;
if (max < absW) max = absW;
if (max == T (0)) return T (0);
// // Do not replace the divisions by max with multiplications by 1/max. // Computing 1/max can overflow but the divisions below will always // produce results less than or equal to 1. //
absX /= max; absY /= max; absZ /= max; absW /= max;
return max * Math<T>::sqrt (absX * absX + absY * absY + absZ * absZ + absW * absW); }
template <class T> inline T Vec4<T>::length () const { T length2 = dot (*this);
if (length2 < T (2) * limits<T>::smallest()) return lengthTiny();
return Math<T>::sqrt (length2); }
template <class T> inline T Vec4<T>::length2 () const { return dot (*this); }
template <class T> const Vec4<T> & Vec4<T>::normalize () { T l = length();
if (l != T (0)) { // // Do not replace the divisions by l with multiplications by 1/l. // Computing 1/l can overflow but the divisions below will always // produce results less than or equal to 1. //
x /= l; y /= l; z /= l; w /= l; }
return *this; }
template <class T> const Vec4<T> & Vec4<T>::normalizeExc () throw (IEX_NAMESPACE::MathExc) { T l = length();
if (l == T (0)) throw NullVecExc ("Cannot normalize null vector.");
x /= l; y /= l; z /= l; w /= l; return *this; }
template <class T> inline const Vec4<T> & Vec4<T>::normalizeNonNull () { T l = length(); x /= l; y /= l; z /= l; w /= l; return *this; }
template <class T> Vec4<T> Vec4<T>::normalized () const { T l = length();
if (l == T (0)) return Vec4 (T (0));
return Vec4 (x / l, y / l, z / l, w / l); }
template <class T> Vec4<T> Vec4<T>::normalizedExc () const throw (IEX_NAMESPACE::MathExc) { T l = length();
if (l == T (0)) throw NullVecExc ("Cannot normalize null vector.");
return Vec4 (x / l, y / l, z / l, w / l); }
template <class T> inline Vec4<T> Vec4<T>::normalizedNonNull () const { T l = length(); return Vec4 (x / l, y / l, z / l, w / l); }
//----------------------------- // Stream output implementation //-----------------------------
template <class T> std::ostream & operator << (std::ostream &s, const Vec2<T> &v) { return s << '(' << v.x << ' ' << v.y << ')'; }
template <class T> std::ostream & operator << (std::ostream &s, const Vec3<T> &v) { return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')'; }
template <class T> std::ostream & operator << (std::ostream &s, const Vec4<T> &v) { return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ' ' << v.w << ')'; }
//----------------------------------------- // Implementation of reverse multiplication //-----------------------------------------
template <class T> inline Vec2<T> operator * (T a, const Vec2<T> &v) { return Vec2<T> (a * v.x, a * v.y); }
template <class T> inline Vec3<T> operator * (T a, const Vec3<T> &v) { return Vec3<T> (a * v.x, a * v.y, a * v.z); }
template <class T> inline Vec4<T> operator * (T a, const Vec4<T> &v) { return Vec4<T> (a * v.x, a * v.y, a * v.z, a * v.w); }
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER #pragma warning(pop) #endif
IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
#endif // INCLUDED_IMATHVEC_H
|