1491 lines
29 KiB
C++
1491 lines
29 KiB
C++
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2004, 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 and 3D point/vector class templates!
|
|
//
|
|
//----------------------------------------------------
|
|
|
|
#include "ImathExc.h"
|
|
#include "ImathLimits.h"
|
|
#include "ImathMath.h"
|
|
|
|
#include <iostream>
|
|
|
|
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
|
|
// suppress exception specification warnings
|
|
#pragma warning(disable:4290)
|
|
#endif
|
|
|
|
|
|
namespace Imath {
|
|
|
|
|
|
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::MathExc);
|
|
const Vec2 & normalizeNonNull ();
|
|
|
|
Vec2<T> normalized () const; // does not modify *this
|
|
Vec2<T> normalizedExc () const throw (Iex::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> or a Vec3<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);
|
|
|
|
|
|
//----------------------
|
|
// 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::MathExc);
|
|
const Vec3 & normalizeNonNull ();
|
|
|
|
Vec3<T> normalized () const; // does not modify *this
|
|
Vec3<T> normalizedExc () const throw (Iex::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> or a Vec3<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);
|
|
|
|
|
|
//----------------------------------------------------
|
|
// 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);
|
|
|
|
|
|
//-------------------------
|
|
// 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;
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
// Specializations for Vec2<short>, Vec2<int>, Vec3<short>, Vec3<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::MathExc);
|
|
|
|
template <> const Vec2<short> &
|
|
Vec2<short>::normalizeNonNull ();
|
|
|
|
template <> Vec2<short>
|
|
Vec2<short>::normalized () const;
|
|
|
|
template <> Vec2<short>
|
|
Vec2<short>::normalizedExc () const throw (Iex::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::MathExc);
|
|
|
|
template <> const Vec2<int> &
|
|
Vec2<int>::normalizeNonNull ();
|
|
|
|
template <> Vec2<int>
|
|
Vec2<int>::normalized () const;
|
|
|
|
template <> Vec2<int>
|
|
Vec2<int>::normalizedExc () const throw (Iex::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::MathExc);
|
|
|
|
template <> const Vec3<short> &
|
|
Vec3<short>::normalizeNonNull ();
|
|
|
|
template <> Vec3<short>
|
|
Vec3<short>::normalized () const;
|
|
|
|
template <> Vec3<short>
|
|
Vec3<short>::normalizedExc () const throw (Iex::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::MathExc);
|
|
|
|
template <> const Vec3<int> &
|
|
Vec3<int>::normalizeNonNull ();
|
|
|
|
template <> Vec3<int>
|
|
Vec3<int>::normalized () const;
|
|
|
|
template <> Vec3<int>
|
|
Vec3<int>::normalizedExc () const throw (Iex::MathExc);
|
|
|
|
template <> Vec3<int>
|
|
Vec3<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::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::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 >= 0)? x: -x;
|
|
T absY = (y >= 0)? y: -y;
|
|
|
|
T max = absX;
|
|
|
|
if (max < absY)
|
|
max = absY;
|
|
|
|
if (max == 0)
|
|
return 0;
|
|
|
|
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 < 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 != 0)
|
|
{
|
|
x /= l;
|
|
y /= l;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
const Vec2<T> &
|
|
Vec2<T>::normalizeExc () throw (Iex::MathExc)
|
|
{
|
|
T l = length();
|
|
|
|
if (l == 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 == 0)
|
|
return Vec2 (T (0));
|
|
|
|
return Vec2 (x / l, y / l);
|
|
}
|
|
|
|
template <class T>
|
|
Vec2<T>
|
|
Vec2<T>::normalizedExc () const throw (Iex::MathExc)
|
|
{
|
|
T l = length();
|
|
|
|
if (l == 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 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::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::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 >= 0)? x: -x;
|
|
T absY = (y >= 0)? y: -y;
|
|
T absZ = (z >= 0)? z: -z;
|
|
|
|
T max = absX;
|
|
|
|
if (max < absY)
|
|
max = absY;
|
|
|
|
if (max < absZ)
|
|
max = absZ;
|
|
|
|
if (max == 0)
|
|
return 0;
|
|
|
|
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 < 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 != 0)
|
|
{
|
|
x /= l;
|
|
y /= l;
|
|
z /= l;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template <class T>
|
|
const Vec3<T> &
|
|
Vec3<T>::normalizeExc () throw (Iex::MathExc)
|
|
{
|
|
T l = length();
|
|
|
|
if (l == 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 == 0)
|
|
return Vec3 (T (0));
|
|
|
|
return Vec3 (x / l, y / l, z / l);
|
|
}
|
|
|
|
template <class T>
|
|
Vec3<T>
|
|
Vec3<T>::normalizedExc () const throw (Iex::MathExc)
|
|
{
|
|
T l = length();
|
|
|
|
if (l == 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);
|
|
}
|
|
|
|
|
|
//-----------------------------
|
|
// 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 << ')';
|
|
}
|
|
|
|
|
|
//-----------------------------------------
|
|
// 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);
|
|
}
|
|
|
|
|
|
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
|
|
#pragma warning(default:4290)
|
|
#endif
|
|
|
|
} // namespace Imath
|
|
|
|
#endif
|