Merge branch 'matrix4' into feature/transform-matrix
This commit is contained in:
		
						commit
						5b25b402c7
					
				
					 8 changed files with 580 additions and 390 deletions
				
			
		| 
						 | 
				
			
			@ -15,60 +15,7 @@
 | 
			
		|||
#include "basics/matrix.hh"
 | 
			
		||||
#include "basics/ray.hh"
 | 
			
		||||
#include "basics/types.hh"
 | 
			
		||||
#include "basics/util.hh"
 | 
			
		||||
#include "basics/vector.hh"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A very small constant. If a value is between EPSILON and 0.0, it is
 | 
			
		||||
 * considered to be zero.
 | 
			
		||||
 */
 | 
			
		||||
const Double EPSILON = 1.0e-10;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The maximum distance a ray can travel. This is the maximum value t can be.
 | 
			
		||||
 */
 | 
			
		||||
const Double MAX_DISTANCE = 1.0e7;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Determine if the value is "close enough" to zero. Takes the absolute value
 | 
			
		||||
 * and compares it to `EPSILON`.
 | 
			
		||||
 *
 | 
			
		||||
 * @see EPSILON
 | 
			
		||||
 *
 | 
			
		||||
 * @param [in] value    The value to check
 | 
			
		||||
 * @returns `true` if the value is close enough to zero
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline bool
 | 
			
		||||
NearZero(const T value)
 | 
			
		||||
{
 | 
			
		||||
    return std::fabs(value) < EPSILON;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Determine if two values are "close enough" to be considered equal. Subtracts
 | 
			
		||||
 * one from the other and checks if the result is near zero.
 | 
			
		||||
 *
 | 
			
		||||
 * @see NearZero
 | 
			
		||||
 *
 | 
			
		||||
 * @param [in] left     The left parameter
 | 
			
		||||
 * @param [in] right    The right parameter
 | 
			
		||||
 * @returns `true` if the values are close enough to be equal
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline bool
 | 
			
		||||
NearlyEqual(const T left,
 | 
			
		||||
            const T right)
 | 
			
		||||
{
 | 
			
		||||
    return NearZero(left - right);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline bool
 | 
			
		||||
TooFar(const Double& value)
 | 
			
		||||
{
 | 
			
		||||
    return value > MAX_DISTANCE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* __BASICS_BASICS_HH__ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,27 +3,269 @@
 | 
			
		|||
 * Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "matrix.hh"
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
#include "basics/matrix.hh"
 | 
			
		||||
 | 
			
		||||
#include "basics/util.hh"
 | 
			
		||||
#include "basics/vector.hh"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace charles {
 | 
			
		||||
namespace basics {
 | 
			
		||||
 | 
			
		||||
#pragma mark Static Methods
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::Zero --
 | 
			
		||||
 */
 | 
			
		||||
/* static */ Matrix4
 | 
			
		||||
Matrix4::Zero()
 | 
			
		||||
{
 | 
			
		||||
    Matrix4 m;
 | 
			
		||||
    bzero(m.mData, sizeof(Double) * 16);
 | 
			
		||||
    return m;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::Identity --
 | 
			
		||||
 */
 | 
			
		||||
/* static */ Matrix4
 | 
			
		||||
Matrix4::Identity()
 | 
			
		||||
{
 | 
			
		||||
    auto m = Matrix4::Zero();
 | 
			
		||||
    for (size_t i = 0; i < 4; i++) {
 | 
			
		||||
        m(i,i) = 1.0;
 | 
			
		||||
    }
 | 
			
		||||
    return m;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::TranslationMatrix --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4
 | 
			
		||||
TranslationMatrix(const Double& x,
 | 
			
		||||
                  const Double& y,
 | 
			
		||||
                  const Double& z)
 | 
			
		||||
/* static */ Matrix4
 | 
			
		||||
Matrix4::Translation(Double x,
 | 
			
		||||
                     Double y,
 | 
			
		||||
                     Double z)
 | 
			
		||||
{
 | 
			
		||||
    Matrix4 m = Matrix4::Identity();
 | 
			
		||||
    m(0, 3) = x;
 | 
			
		||||
    m(1, 3) = y;
 | 
			
		||||
    m(2, 3) = z;
 | 
			
		||||
    m(0,3) = x;
 | 
			
		||||
    m(1,3) = y;
 | 
			
		||||
    m(2,3) = z;
 | 
			
		||||
    return m;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark Constructors and Assignment
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::Matrix4 --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4::Matrix4()
 | 
			
		||||
    : mData()
 | 
			
		||||
{ }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::Matrix4 --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4::Matrix4(const Double data[16])
 | 
			
		||||
{
 | 
			
		||||
    memcpy(mData, data, sizeof(Double) * 16);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::Matrix4 --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4::Matrix4(const Matrix4 &rhs)
 | 
			
		||||
    : Matrix4(rhs.mData)
 | 
			
		||||
{ }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator= --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4&
 | 
			
		||||
Matrix4::operator=(const Matrix4 &rhs)
 | 
			
		||||
{
 | 
			
		||||
    memcpy(mData, rhs.mData, sizeof(Double) * 16);
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark Boolean Operators
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator== --
 | 
			
		||||
 */
 | 
			
		||||
bool
 | 
			
		||||
Matrix4::operator==(const Matrix4 &rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    for (int i = 0; i < 16; i++) {
 | 
			
		||||
        if (!NearlyEqual(mData[i], rhs.mData[i])) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator!= --
 | 
			
		||||
 */
 | 
			
		||||
bool
 | 
			
		||||
Matrix4::operator!=(const Matrix4 &rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return !(*this == rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark Element Access
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator() --
 | 
			
		||||
 */
 | 
			
		||||
Double&
 | 
			
		||||
Matrix4::operator()(UInt i,
 | 
			
		||||
                    UInt j)
 | 
			
		||||
{
 | 
			
		||||
    if (i >= 4 || j >= 4) {
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss << "matrix index out of bounds: i = " << i << ", j = " << j;
 | 
			
		||||
        throw std::out_of_range(ss.str());
 | 
			
		||||
    }
 | 
			
		||||
    return mData[i*4 + j];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator() --
 | 
			
		||||
 */
 | 
			
		||||
Double
 | 
			
		||||
Matrix4::operator()(UInt i,
 | 
			
		||||
                    UInt j)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    if (i >= 4 || j >= 4) {
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss << "matrix index out of bounds: i = " << i << ", j = " << j;
 | 
			
		||||
        throw std::out_of_range(ss.str());
 | 
			
		||||
    }
 | 
			
		||||
    return mData[i*4 + j];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::CArray --
 | 
			
		||||
 */
 | 
			
		||||
const Double*
 | 
			
		||||
Matrix4::CArray()
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return mData;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark Maths
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator* --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4
 | 
			
		||||
Matrix4::operator*(Double rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return Matrix4(*this) *= rhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator/ --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4
 | 
			
		||||
Matrix4::operator/(Double rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return Matrix4(*this) /= rhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator*= --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4&
 | 
			
		||||
Matrix4::operator*=(Double rhs)
 | 
			
		||||
{
 | 
			
		||||
    for (UInt i = 0; i < 16; i++) {
 | 
			
		||||
        mData[i] *= rhs;
 | 
			
		||||
    }
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator/= --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4&
 | 
			
		||||
Matrix4::operator/=(Double rhs)
 | 
			
		||||
{
 | 
			
		||||
    return *this *= (1.0 / rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator* --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4
 | 
			
		||||
Matrix4::operator*(const Matrix4& rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    Matrix4 result;
 | 
			
		||||
    for (UInt i = 0; i < 4; i++) {
 | 
			
		||||
        for (UInt j = 0; j < 4; j++) {
 | 
			
		||||
            /* Each cell is Sigma(k=0, M)(lhs[ik] * rhs[kj]) */
 | 
			
		||||
            result(i,j) = 0.0;
 | 
			
		||||
            for (UInt k = 0; k < 4; k++) {
 | 
			
		||||
                result(i,j) += mData[i*4 + k] * rhs(k,j);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix4::operator* --
 | 
			
		||||
 */
 | 
			
		||||
Vector4
 | 
			
		||||
Matrix4::operator*(const Vector4 &rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    Vector4 result;
 | 
			
		||||
    for (UInt i = 0; i < 4; i++) {
 | 
			
		||||
        result(i) = 0.0;
 | 
			
		||||
        for (UInt k = 0; k < 4; k++) {
 | 
			
		||||
            result(i) += mData[i*4 + k] * rhs(k);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::operator* --
 | 
			
		||||
 */
 | 
			
		||||
Matrix4
 | 
			
		||||
operator*(Double lhs,
 | 
			
		||||
          const Matrix4& rhs)
 | 
			
		||||
{
 | 
			
		||||
    /* Scalar multiplication is commutative. */
 | 
			
		||||
    return rhs * lhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} /* namespace mespace  */
 | 
			
		||||
} /* namespace charles */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,274 +16,71 @@
 | 
			
		|||
namespace charles {
 | 
			
		||||
namespace basics {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A generic, templated Matrix class taking two template parameters. `N` is the
 | 
			
		||||
 * number of rows. `M` is the number of columns. If `M` is not specified, the
 | 
			
		||||
 * matrix will be square.
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M = N>
 | 
			
		||||
struct Matrix
 | 
			
		||||
struct Vector4;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** A 4x4 matrix, used for 3D transforms. */
 | 
			
		||||
struct Matrix4
 | 
			
		||||
{
 | 
			
		||||
    /** Construct an N x M matrix of zeros. */
 | 
			
		||||
    static Matrix<N,M> Zero();
 | 
			
		||||
    /** Create a 4x4 matrix of zeros. */
 | 
			
		||||
    static Matrix4 Zero();
 | 
			
		||||
 | 
			
		||||
    /** Create a 4x4 identity matrix. */
 | 
			
		||||
    static Matrix4 Identity();
 | 
			
		||||
 | 
			
		||||
    /** Create a 4x4 translation matrix. */
 | 
			
		||||
    static Matrix4 Translation(Double x, Double y, Double z);
 | 
			
		||||
 | 
			
		||||
    Matrix4();
 | 
			
		||||
    Matrix4(const Double *data);
 | 
			
		||||
    Matrix4(const Matrix4 &rhs);
 | 
			
		||||
 | 
			
		||||
    Matrix4& operator=(const Matrix4 &rhs);
 | 
			
		||||
 | 
			
		||||
    bool operator==(const Matrix4 &rhs) const;
 | 
			
		||||
    bool operator!=(const Matrix4 &rhs) const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct an N x M identity matrix. Identity matrices are always square.
 | 
			
		||||
     * It is a (compile time) error to call Identity on a Matrix class where
 | 
			
		||||
     * N != M.
 | 
			
		||||
     * Get the ij'th item. In debug builds, this will assert if i or j are
 | 
			
		||||
     * outside the bounds of the array.
 | 
			
		||||
     */
 | 
			
		||||
    static Matrix<N,M> Identity();
 | 
			
		||||
 | 
			
		||||
    Matrix();
 | 
			
		||||
    Matrix(const Double data[N*M]);
 | 
			
		||||
    Matrix(const Matrix<N,M>& rhs);
 | 
			
		||||
 | 
			
		||||
    Matrix<N,M>& operator=(const Matrix<N,M>& rhs);
 | 
			
		||||
 | 
			
		||||
    bool operator==(const Matrix<N,M>& rhs) const;
 | 
			
		||||
    bool operator!=(const Matrix<N,M>& rhs) const;
 | 
			
		||||
 | 
			
		||||
    /** Value accessor. Get the ij'th item. */
 | 
			
		||||
    Double& operator()(UInt i, UInt j);
 | 
			
		||||
    Double  operator()(UInt i, UInt j) const;
 | 
			
		||||
 | 
			
		||||
    /** Get the underlying C array */
 | 
			
		||||
    const Double *CArray() const;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * TODO: For completeness, matrix addition and subtraction, though I have
 | 
			
		||||
     * yet to find a need for them...
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @defgroup Scalar multiplication
 | 
			
		||||
     * @{
 | 
			
		||||
     */
 | 
			
		||||
    Matrix<N,M> operator*(const Double& rhs) const;
 | 
			
		||||
    Matrix<N,M>& operator*=(const Double& rhs);
 | 
			
		||||
    Matrix<N,M> operator/(const Double& rhs) const;
 | 
			
		||||
    Matrix<N,M>& operator/=(const Double& rhs);
 | 
			
		||||
    Matrix4  operator*(Double rhs) const;
 | 
			
		||||
    Matrix4  operator/(Double rhs) const;
 | 
			
		||||
    Matrix4& operator*=(Double rhs);
 | 
			
		||||
    Matrix4& operator/=(Double rhs);
 | 
			
		||||
    /** @} */
 | 
			
		||||
 | 
			
		||||
    /** Matrix multiplication */
 | 
			
		||||
    template<UInt P>
 | 
			
		||||
    Matrix<N,P> operator*(Matrix<M,P> rhs) const;
 | 
			
		||||
 | 
			
		||||
    /** Get the underlying C array */
 | 
			
		||||
    const Double* CArray() const;
 | 
			
		||||
    /**
 | 
			
		||||
     * @defgroup Matrix multiplication
 | 
			
		||||
     * @{
 | 
			
		||||
     */
 | 
			
		||||
    Matrix4 operator*(const Matrix4 &rhs) const;
 | 
			
		||||
    Vector4 operator*(const Vector4 &rhs) const;
 | 
			
		||||
    /** @} */
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    /** The matrix data, stored in row-major format. */
 | 
			
		||||
    Double mData[N * M];
 | 
			
		||||
    /** The matrix data */
 | 
			
		||||
    Double mData[16];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Scalar multiplication, scalar factor on the left. */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Matrix<N,M> operator*(const Double& lhs, const Matrix<N,M>& rhs);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** A standard 4x4 matrix. */
 | 
			
		||||
typedef Matrix<4> Matrix4;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a translation matrix that will translate a vector to the given
 | 
			
		||||
 * coordinates.
 | 
			
		||||
 */
 | 
			
		||||
Matrix4 TranslationMatrix(const Double& x, const Double& y, const Double& z);
 | 
			
		||||
 | 
			
		||||
#pragma mark Static Methods
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::Zero --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
/* static */ Matrix<N,M>
 | 
			
		||||
Matrix<N,M>::Zero()
 | 
			
		||||
{
 | 
			
		||||
    Matrix<N,M> m;
 | 
			
		||||
    bzero(m.mData, sizeof(Double) * N * M);
 | 
			
		||||
    return m;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::Identity --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
/* static */ Matrix<N,M>
 | 
			
		||||
Matrix<N,M>::Identity()
 | 
			
		||||
{
 | 
			
		||||
    static_assert(N == M, "Identity matrices must be square.");
 | 
			
		||||
 | 
			
		||||
    auto m = Matrix<N,M>::Zero();
 | 
			
		||||
    for (size_t i = 0; i < N; i++) {
 | 
			
		||||
        m(i,i) = 1.0;
 | 
			
		||||
    }
 | 
			
		||||
    return m;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark Instance Methods
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::Matrix --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Matrix<N,M>::Matrix()
 | 
			
		||||
    : mData()
 | 
			
		||||
{ }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::Matrix --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Matrix<N,M>::Matrix(const Double data[N*M])
 | 
			
		||||
{
 | 
			
		||||
    memcpy(mData, data, sizeof(Double) * N * M);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::Matrix --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Matrix<N,M>::Matrix(const Matrix<N,M>& rhs)
 | 
			
		||||
    : Matrix(rhs.mData)
 | 
			
		||||
{ }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::operator= --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Matrix<N,M>&
 | 
			
		||||
Matrix<N,M>::operator=(const Matrix<N,M>& rhs)
 | 
			
		||||
{
 | 
			
		||||
    memcpy(mData, rhs.mData, sizeof(Double) * N * M);
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::operator== --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
bool
 | 
			
		||||
Matrix<N,M>::operator==(const Matrix<N,M>& rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    for (UInt i = 0; i < N*M; i++) {
 | 
			
		||||
        /* TODO: Use NearlyEqual. */
 | 
			
		||||
        if (mData[i] != rhs.mData[i]) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::operator!= --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
bool
 | 
			
		||||
Matrix<N,M>::operator!=(const Matrix<N,M>& rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return !(*this == rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::operator() --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Double&
 | 
			
		||||
Matrix<N,M>::operator()(UInt i, UInt j)
 | 
			
		||||
{
 | 
			
		||||
    assert(i < N && j < M);
 | 
			
		||||
    return mData[i * N + j];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::operator* --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Matrix<N,M>
 | 
			
		||||
Matrix<N,M>::operator*(const Double& rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return Matrix<N,M>(*this) *= rhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Matrix<N,M>&
 | 
			
		||||
Matrix<N,M>::operator*=(const Double& rhs)
 | 
			
		||||
{
 | 
			
		||||
    for (size_t i = 0; i < N*M; i++) {
 | 
			
		||||
        mData[i] *= rhs;
 | 
			
		||||
    }
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Matrix<N,M>
 | 
			
		||||
Matrix<N,M>::operator/(const Double& rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return Matrix<N,M>(*this) /= rhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Matrix<N,M>&
 | 
			
		||||
Matrix<N,M>::operator/=(const Double& rhs)
 | 
			
		||||
{
 | 
			
		||||
    return *this *= (1.0 / rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::operator* --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
template<UInt P>
 | 
			
		||||
Matrix<N,P>
 | 
			
		||||
Matrix<N,M>::operator*(Matrix<M,P> rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    Matrix<N,P> result;
 | 
			
		||||
    for (UInt i = 0; i < N; i++) {
 | 
			
		||||
        for (UInt j = 0; j < P; j++) {
 | 
			
		||||
            /* Each cell is Sigma(k=0, M)(lhs[ik] * rhs[kj]) */
 | 
			
		||||
            result(i, j) = 0.0;
 | 
			
		||||
            for (UInt k = 0; k < M; k++) {
 | 
			
		||||
                result(i, j) += mData[i*N + k] * rhs(k, j);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Matrix<>::CArray --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
const Double*
 | 
			
		||||
Matrix<N,M>::CArray()
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return mData;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::operator* --
 | 
			
		||||
 */
 | 
			
		||||
template<UInt N, UInt M>
 | 
			
		||||
Matrix<N,M>
 | 
			
		||||
operator*(const Double& lhs,
 | 
			
		||||
          const Matrix<N,M>& rhs)
 | 
			
		||||
{
 | 
			
		||||
    return rhs * lhs;
 | 
			
		||||
}
 | 
			
		||||
Matrix4 operator*(Double lhs, const Matrix4 &rhs);
 | 
			
		||||
 | 
			
		||||
} /* namespace basics */
 | 
			
		||||
} /* namespace charles */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										68
									
								
								src/basics/util.hh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/basics/util.hh
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,68 @@
 | 
			
		|||
/* util.hh
 | 
			
		||||
 * vim: set tw=80:
 | 
			
		||||
 * Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __BASICS_UTIL_HH__
 | 
			
		||||
#define __BASICS_UTIL_HH__
 | 
			
		||||
 | 
			
		||||
#include <cmath>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A very small constant. If a value is between EPSILON and 0.0, it is
 | 
			
		||||
 * considered to be zero.
 | 
			
		||||
 */
 | 
			
		||||
const Double EPSILON = 1.0e-10;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The maximum distance a ray can travel. This is the maximum value t can be.
 | 
			
		||||
 */
 | 
			
		||||
const Double MAX_DISTANCE = 1.0e7;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Determine if the value is "close enough" to zero. Takes the absolute value
 | 
			
		||||
 * and compares it to `EPSILON`.
 | 
			
		||||
 *
 | 
			
		||||
 * @see EPSILON
 | 
			
		||||
 *
 | 
			
		||||
 * @param [in] value    The value to check
 | 
			
		||||
 * @returns `true` if the value is close enough to zero
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline bool
 | 
			
		||||
NearZero(T value)
 | 
			
		||||
{
 | 
			
		||||
    return std::fabs(value) < EPSILON;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Determine if two values are "close enough" to be considered equal. Subtracts
 | 
			
		||||
 * one from the other and checks if the result is near zero.
 | 
			
		||||
 *
 | 
			
		||||
 * @see NearZero
 | 
			
		||||
 *
 | 
			
		||||
 * @param [in] left     The left parameter
 | 
			
		||||
 * @param [in] right    The right parameter
 | 
			
		||||
 * @returns `true` if the values are close enough to be equal
 | 
			
		||||
 */
 | 
			
		||||
template <typename T, typename U>
 | 
			
		||||
inline bool
 | 
			
		||||
NearlyEqual(T left,
 | 
			
		||||
            U right)
 | 
			
		||||
{
 | 
			
		||||
    return NearZero(left - right);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline bool
 | 
			
		||||
TooFar(const Double& value)
 | 
			
		||||
{
 | 
			
		||||
    return value > MAX_DISTANCE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* __BASICS_UTIL_HH__ */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4,19 +4,35 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include <cmath>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
#include "basics/vector.hh"
 | 
			
		||||
 | 
			
		||||
#include "basics/util.hh"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace charles {
 | 
			
		||||
namespace basics {
 | 
			
		||||
 | 
			
		||||
#pragma mark Constructors and Assignment
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::Vector4 --
 | 
			
		||||
 */
 | 
			
		||||
Vector4::Vector4(const Double& x,
 | 
			
		||||
                 const Double& y,
 | 
			
		||||
                 const Double& z)
 | 
			
		||||
Vector4::Vector4()
 | 
			
		||||
{
 | 
			
		||||
    bzero(mData, sizeof(Double) * 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::Vector4 --
 | 
			
		||||
 */
 | 
			
		||||
Vector4::Vector4(Double x,
 | 
			
		||||
                 Double y,
 | 
			
		||||
                 Double z)
 | 
			
		||||
{
 | 
			
		||||
    mData[0] = x;
 | 
			
		||||
    mData[1] = y;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,11 +41,17 @@ Vector4::Vector4(const Double& x,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Vector4::Vector4(const Matrix<4,1>& rhs)
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator= --
 | 
			
		||||
 */
 | 
			
		||||
Vector4&
 | 
			
		||||
Vector4::operator=(const Vector4 &rhs)
 | 
			
		||||
{
 | 
			
		||||
    memcpy(mData, rhs.CArray(), sizeof(Double) * 4);
 | 
			
		||||
    memcpy(mData, rhs.mData, sizeof(Double) * 4);
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark Component Access
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::X --
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +62,11 @@ Vector4::X()
 | 
			
		|||
    return mData[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Double&
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::X --
 | 
			
		||||
 */
 | 
			
		||||
Double
 | 
			
		||||
Vector4::X()
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +84,10 @@ Vector4::Y()
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const Double&
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::Y --
 | 
			
		||||
 */
 | 
			
		||||
Double
 | 
			
		||||
Vector4::Y()
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +108,7 @@ Vector4::Z()
 | 
			
		|||
/*
 | 
			
		||||
 * charles::basics::Vector4::Z --
 | 
			
		||||
 */
 | 
			
		||||
const Double&
 | 
			
		||||
Double
 | 
			
		||||
Vector4::Z()
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -87,35 +116,143 @@ Vector4::Z()
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
Double&
 | 
			
		||||
Vector4::operator()(UInt i)
 | 
			
		||||
{
 | 
			
		||||
    if (i >= 4) {
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss << "vector index out of bounds: i = " << i;
 | 
			
		||||
        throw std::out_of_range(ss.str());
 | 
			
		||||
    }
 | 
			
		||||
    return mData[i];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Double
 | 
			
		||||
Vector4::operator()(UInt i)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    if (i >= 4) {
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss << "vector index out of bounds: i = " << i;
 | 
			
		||||
        throw std::out_of_range(ss.str());
 | 
			
		||||
    }
 | 
			
		||||
    return mData[i];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::CArray --
 | 
			
		||||
 */
 | 
			
		||||
const Double*
 | 
			
		||||
Vector4::CArray()
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return mData;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark Boolean Operators
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator== --
 | 
			
		||||
 */
 | 
			
		||||
bool
 | 
			
		||||
Vector4::operator==(const Vector4 &rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    for (UInt i = 0; i < 4; i++) {
 | 
			
		||||
        if (!NearlyEqual(mData[i], rhs.mData[i])) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator!= --
 | 
			
		||||
 */
 | 
			
		||||
bool
 | 
			
		||||
Vector4::operator!=(const Vector4 &rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return !(*this == rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#pragma mark Maths
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator* --
 | 
			
		||||
 */
 | 
			
		||||
Vector4
 | 
			
		||||
Vector4::operator*(const Double& rhs)
 | 
			
		||||
Vector4::operator*(Double rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<Matrix<4,1>>(*this) * rhs;
 | 
			
		||||
    return Vector4(*this) *= rhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator* --
 | 
			
		||||
 */
 | 
			
		||||
Vector4
 | 
			
		||||
Vector4::operator/(Double rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return Vector4(*this) /= rhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator*= --
 | 
			
		||||
 */
 | 
			
		||||
Vector4&
 | 
			
		||||
Vector4::operator*=(Double rhs)
 | 
			
		||||
{
 | 
			
		||||
    for (int i = 0; i < 4; i++) {
 | 
			
		||||
        mData[i] *= rhs;
 | 
			
		||||
    }
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator/= --
 | 
			
		||||
 */
 | 
			
		||||
Vector4&
 | 
			
		||||
Vector4::operator/=(Double rhs)
 | 
			
		||||
{
 | 
			
		||||
    return *this *= (1.0 / rhs);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator+ --
 | 
			
		||||
 */
 | 
			
		||||
Vector4
 | 
			
		||||
Vector4::operator+(const Vector4& rhs)
 | 
			
		||||
Vector4::operator+(const Vector4 &rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return Vector4(*this) += rhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator- --
 | 
			
		||||
 */
 | 
			
		||||
Vector4
 | 
			
		||||
Vector4::operator-(const Vector4 &rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return Vector4(*this) -= rhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator+= --
 | 
			
		||||
 */
 | 
			
		||||
Vector4&
 | 
			
		||||
Vector4::operator+=(const Vector4& rhs)
 | 
			
		||||
Vector4::operator+=(const Vector4 &rhs)
 | 
			
		||||
{
 | 
			
		||||
    mData[0] += rhs.mData[0];
 | 
			
		||||
    mData[1] += rhs.mData[1];
 | 
			
		||||
| 
						 | 
				
			
			@ -124,22 +261,11 @@ Vector4::operator+=(const Vector4& rhs)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator- --
 | 
			
		||||
 */
 | 
			
		||||
Vector4
 | 
			
		||||
Vector4::operator-(const Vector4& rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return Vector4(*this) -= rhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * charles::basics::Vector4::operator-= --
 | 
			
		||||
 */
 | 
			
		||||
Vector4&
 | 
			
		||||
Vector4::operator-=(const Vector4& rhs)
 | 
			
		||||
Vector4::operator-=(const Vector4 &rhs)
 | 
			
		||||
{
 | 
			
		||||
    return *this += -rhs;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +289,7 @@ Double
 | 
			
		|||
Vector4::Length2()
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return mData[0] * mData[0] + mData[1] * mData[1] + mData[2] * mData[2];
 | 
			
		||||
    return X()*X() + Y()*Y() + Z()*Z();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +311,7 @@ Double
 | 
			
		|||
Vector4::Dot(const Vector4& rhs)
 | 
			
		||||
    const
 | 
			
		||||
{
 | 
			
		||||
    return mData[0] * rhs.mData[0] + mData[1] * rhs.mData[1] + mData[2] * rhs.mData[2];
 | 
			
		||||
    return X()*rhs.X() + Y()*rhs.Y() + Z()*rhs.Z();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -208,12 +334,7 @@ Vector4::Cross(const Vector4& rhs)
 | 
			
		|||
Vector4&
 | 
			
		||||
Vector4::Normalize()
 | 
			
		||||
{
 | 
			
		||||
    /* XXX: Is there some way to do this with the Matrix<>::operator/? */
 | 
			
		||||
    const Double len = Length();
 | 
			
		||||
    X() = X() / len;
 | 
			
		||||
    Y() = Y() / len;
 | 
			
		||||
    Z() = Z() / len;
 | 
			
		||||
    return *this;
 | 
			
		||||
    return *this /= Length();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -221,7 +342,7 @@ Vector4::Normalize()
 | 
			
		|||
 * charles::basics::operator* --
 | 
			
		||||
 */
 | 
			
		||||
Vector4
 | 
			
		||||
operator*(const Double& lhs,
 | 
			
		||||
operator*(Double lhs,
 | 
			
		||||
          const Vector4& rhs)
 | 
			
		||||
{
 | 
			
		||||
    return rhs * lhs;
 | 
			
		||||
| 
						 | 
				
			
			@ -232,9 +353,9 @@ operator*(const Double& lhs,
 | 
			
		|||
 * charles::basics::Normalized --
 | 
			
		||||
 */
 | 
			
		||||
Vector4
 | 
			
		||||
Normalized(const Vector4& v)
 | 
			
		||||
Normalized(Vector4 v)
 | 
			
		||||
{
 | 
			
		||||
    return Vector4(v).Normalize();
 | 
			
		||||
    return v.Normalize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,34 +15,56 @@
 | 
			
		|||
namespace charles {
 | 
			
		||||
namespace basics {
 | 
			
		||||
 | 
			
		||||
template<UInt N>
 | 
			
		||||
struct Vector
 | 
			
		||||
    : public Matrix<N,1>
 | 
			
		||||
{ };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** A 4x1 matrix, used for specifying points and directions in 3D space. */
 | 
			
		||||
struct Vector4
 | 
			
		||||
    : public Vector<4>
 | 
			
		||||
{
 | 
			
		||||
    Vector4(const Double& x = 0.0, const Double& y = 0.0, const Double& z = 0.0);
 | 
			
		||||
    Vector4(const Matrix<4,1>& m);
 | 
			
		||||
    Vector4();
 | 
			
		||||
    Vector4(Double x, Double y, Double z);
 | 
			
		||||
 | 
			
		||||
    Vector4 &operator=(const Vector4 &rhs);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @defgroup Component access
 | 
			
		||||
     * @{
 | 
			
		||||
     */
 | 
			
		||||
    Double& X();
 | 
			
		||||
    const Double& X() const;
 | 
			
		||||
    Double  X() const;
 | 
			
		||||
    Double& Y();
 | 
			
		||||
    const Double& Y() const;
 | 
			
		||||
    Double  Y() const;
 | 
			
		||||
    Double& Z();
 | 
			
		||||
    const Double& Z() const;
 | 
			
		||||
    Double  Z() const;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    Vector4 operator*(const Double& rhs) const;
 | 
			
		||||
#endif
 | 
			
		||||
    Double &operator()(UInt i);
 | 
			
		||||
    Double  operator()(UInt i) const;
 | 
			
		||||
 | 
			
		||||
    Vector4 operator+(const Vector4& rhs) const;
 | 
			
		||||
    Vector4& operator+=(const Vector4& rhs);
 | 
			
		||||
    Vector4 operator-(const Vector4& rhs) const;
 | 
			
		||||
    Vector4& operator-=(const Vector4& rhs);
 | 
			
		||||
    /** Get the underlying C array. */
 | 
			
		||||
    const Double *CArray() const;
 | 
			
		||||
    /** @} */
 | 
			
		||||
 | 
			
		||||
    bool operator==(const Vector4 &rhs) const;
 | 
			
		||||
    bool operator!=(const Vector4 &rhs) const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @defgroup Scalar multiplication
 | 
			
		||||
     * @{
 | 
			
		||||
     */
 | 
			
		||||
    Vector4 operator*(Double rhs) const;
 | 
			
		||||
    Vector4 operator/(Double rhs) const;
 | 
			
		||||
    Vector4 &operator*=(Double rhs);
 | 
			
		||||
    Vector4 &operator/=(Double rhs);
 | 
			
		||||
    /** @} */
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @defgroup Vector addition and subtraction
 | 
			
		||||
     * @{
 | 
			
		||||
     */
 | 
			
		||||
    Vector4 operator+(const Vector4 &rhs) const;
 | 
			
		||||
    Vector4 operator-(const Vector4 &rhs) const;
 | 
			
		||||
    Vector4 &operator+=(const Vector4 &rhs);
 | 
			
		||||
    Vector4 &operator-=(const Vector4 &rhs);
 | 
			
		||||
    /** @} */
 | 
			
		||||
 | 
			
		||||
    /** Negate this vector. */
 | 
			
		||||
    Vector4 operator-() const;
 | 
			
		||||
 | 
			
		||||
    /** Get the length-squared of this vector. */
 | 
			
		||||
| 
						 | 
				
			
			@ -52,30 +74,33 @@ struct Vector4
 | 
			
		|||
    Double Length() const;
 | 
			
		||||
 | 
			
		||||
    /** Get the dot product of `this` and `rhs`. */
 | 
			
		||||
    Double Dot(const Vector4& rhs) const;
 | 
			
		||||
    Double Dot(const Vector4 &rhs) const;
 | 
			
		||||
 | 
			
		||||
    /** Get the cross product of `this` and `rhs`. */
 | 
			
		||||
    Vector4 Cross(const Vector4& rhs) const;
 | 
			
		||||
 | 
			
		||||
    /** Normalize this vector. */
 | 
			
		||||
    Vector4& Normalize();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Double mData[4];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Scalar multiplication of vectors, with the scalar factor on the left. */
 | 
			
		||||
Vector4 operator*(const Double& lhs, const Vector4& rhs);
 | 
			
		||||
Vector4 operator*(Double lhs, const Vector4 &rhs);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Normalize the given vector and return a copy of it. */
 | 
			
		||||
Vector4 Normalized(const Vector4& v);
 | 
			
		||||
/** Normalize a copy of the given vector. */
 | 
			
		||||
Vector4 Normalized(Vector4 v);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Vector4 LinearCombination(const Double k1, const Vector4& v1,
 | 
			
		||||
                          const Double k2, const Vector4& v2,
 | 
			
		||||
                          const Double k3, const Vector4& v3);
 | 
			
		||||
Vector4 LinearCombination(Double k1, const Vector4 &v1,
 | 
			
		||||
                          Double k2, const Vector4 &v2,
 | 
			
		||||
                          Double k3, const Vector4 &v3);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
std::ostream& operator<<(std::ostream& ost, const Vector4& v);
 | 
			
		||||
std::ostream& operator<<(std::ostream &ost, const Vector4 &v);
 | 
			
		||||
 | 
			
		||||
} /* namespace basics */
 | 
			
		||||
} /* namespace charles */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ namespace charles {
 | 
			
		|||
 * charles::Object::Object --
 | 
			
		||||
 */
 | 
			
		||||
Object::Object(const Vector4& origin)
 | 
			
		||||
    : mTranslation(basics::TranslationMatrix(origin.X(), origin.Y(), origin.Z())),
 | 
			
		||||
    : mTranslation(basics::Matrix4::Translation(origin.X(), origin.Y(), origin.Z())),
 | 
			
		||||
      mMaterial()
 | 
			
		||||
{ }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -248,7 +248,7 @@ TEST_F(Matrix4Test, ScalarMultiplication)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_F(Matrix4Test, SquareMatrixMultiplication)
 | 
			
		||||
TEST_F(Matrix4Test, MatrixMatrixMultiplication)
 | 
			
		||||
{
 | 
			
		||||
    const Double p1Expect[] = {1045,  1690,  2735,  4425,
 | 
			
		||||
                               2137,  3454,  5591,  9045,
 | 
			
		||||
| 
						 | 
				
			
			@ -267,20 +267,10 @@ TEST_F(Matrix4Test, SquareMatrixMultiplication)
 | 
			
		|||
    for (int i = 0; i < 16; i++) {
 | 
			
		||||
        EXPECT_EQ(p2.CArray()[i], p2Expect[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Multiplication with the identity matrix produces the same matrix. */
 | 
			
		||||
    Matrix4 p3 = m1 * Matrix4::Identity();
 | 
			
		||||
    for (int i = 0; i < 16; i++) {
 | 
			
		||||
        EXPECT_EQ(p3.CArray()[i], m1.CArray()[i]);
 | 
			
		||||
    }
 | 
			
		||||
    Matrix4 p4 = Matrix4::Identity() * m1;
 | 
			
		||||
    for (int i = 0; i < 16; i++) {
 | 
			
		||||
        EXPECT_EQ(p4.CArray()[i], m1.CArray()[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_F(Matrix4Test, IdentityMultiplication)
 | 
			
		||||
TEST_F(Matrix4Test, MatrixIdentityMultiplication)
 | 
			
		||||
{
 | 
			
		||||
    Matrix4 p1 = m1 * id;
 | 
			
		||||
    for (UInt i = 0; i < 16; i++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -294,7 +284,7 @@ TEST_F(Matrix4Test, IdentityMultiplication)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_F(Matrix4Test, VectorMultiplication)
 | 
			
		||||
TEST_F(Matrix4Test, IdentityVectorMultiplication)
 | 
			
		||||
{
 | 
			
		||||
    Vector4 v1(1, 2, 3);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue