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/matrix.hh"
|
||||||
#include "basics/ray.hh"
|
#include "basics/ray.hh"
|
||||||
#include "basics/types.hh"
|
#include "basics/types.hh"
|
||||||
|
#include "basics/util.hh"
|
||||||
#include "basics/vector.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__ */
|
#endif /* __BASICS_BASICS_HH__ */
|
||||||
|
|
|
@ -3,27 +3,269 @@
|
||||||
* Eryn Wells <eryn@erynwells.me>
|
* 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 charles {
|
||||||
namespace basics {
|
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 --
|
* charles::basics::TranslationMatrix --
|
||||||
*/
|
*/
|
||||||
Matrix4
|
/* static */ Matrix4
|
||||||
TranslationMatrix(const Double& x,
|
Matrix4::Translation(Double x,
|
||||||
const Double& y,
|
Double y,
|
||||||
const Double& z)
|
Double z)
|
||||||
{
|
{
|
||||||
Matrix4 m = Matrix4::Identity();
|
Matrix4 m = Matrix4::Identity();
|
||||||
m(0, 3) = x;
|
m(0,3) = x;
|
||||||
m(1, 3) = y;
|
m(1,3) = y;
|
||||||
m(2, 3) = z;
|
m(2,3) = z;
|
||||||
return m;
|
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 mespace */
|
||||||
} /* namespace charles */
|
} /* namespace charles */
|
||||||
|
|
||||||
|
|
|
@ -16,274 +16,71 @@
|
||||||
namespace charles {
|
namespace charles {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
/**
|
struct Vector4;
|
||||||
* 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.
|
/** A 4x4 matrix, used for 3D transforms. */
|
||||||
*/
|
struct Matrix4
|
||||||
template<UInt N, UInt M = N>
|
|
||||||
struct Matrix
|
|
||||||
{
|
{
|
||||||
/** Construct an N x M matrix of zeros. */
|
/** Create a 4x4 matrix of zeros. */
|
||||||
static Matrix<N,M> Zero();
|
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.
|
* Get the ij'th item. In debug builds, this will assert if i or j are
|
||||||
* It is a (compile time) error to call Identity on a Matrix class where
|
* outside the bounds of the array.
|
||||||
* N != M.
|
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
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
|
* @defgroup Scalar multiplication
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
Matrix<N,M> operator*(const Double& rhs) const;
|
Matrix4 operator*(Double rhs) const;
|
||||||
Matrix<N,M>& operator*=(const Double& rhs);
|
Matrix4 operator/(Double rhs) const;
|
||||||
Matrix<N,M> operator/(const Double& rhs) const;
|
Matrix4& operator*=(Double rhs);
|
||||||
Matrix<N,M>& operator/=(const Double& rhs);
|
Matrix4& operator/=(Double rhs);
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/** Matrix multiplication */
|
/**
|
||||||
template<UInt P>
|
* @defgroup Matrix multiplication
|
||||||
Matrix<N,P> operator*(Matrix<M,P> rhs) const;
|
* @{
|
||||||
|
*/
|
||||||
/** Get the underlying C array */
|
Matrix4 operator*(const Matrix4 &rhs) const;
|
||||||
const Double* CArray() const;
|
Vector4 operator*(const Vector4 &rhs) const;
|
||||||
|
/** @} */
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** The matrix data, stored in row-major format. */
|
/** The matrix data */
|
||||||
Double mData[N * M];
|
Double mData[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Scalar multiplication, scalar factor on the left. */
|
/** Scalar multiplication, scalar factor on the left. */
|
||||||
template<UInt N, UInt M>
|
Matrix4 operator*(Double lhs, const Matrix4 &rhs);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* namespace basics */
|
} /* namespace basics */
|
||||||
} /* namespace charles */
|
} /* 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 <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "basics/vector.hh"
|
#include "basics/vector.hh"
|
||||||
|
|
||||||
|
#include "basics/util.hh"
|
||||||
|
|
||||||
|
|
||||||
namespace charles {
|
namespace charles {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
|
#pragma mark Constructors and Assignment
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* charles::basics::Vector4::Vector4 --
|
* charles::basics::Vector4::Vector4 --
|
||||||
*/
|
*/
|
||||||
Vector4::Vector4(const Double& x,
|
Vector4::Vector4()
|
||||||
const Double& y,
|
{
|
||||||
const Double& z)
|
bzero(mData, sizeof(Double) * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* charles::basics::Vector4::Vector4 --
|
||||||
|
*/
|
||||||
|
Vector4::Vector4(Double x,
|
||||||
|
Double y,
|
||||||
|
Double z)
|
||||||
{
|
{
|
||||||
mData[0] = x;
|
mData[0] = x;
|
||||||
mData[1] = y;
|
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 --
|
* charles::basics::Vector4::X --
|
||||||
|
@ -40,7 +62,11 @@ Vector4::X()
|
||||||
return mData[0];
|
return mData[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Double&
|
|
||||||
|
/*
|
||||||
|
* charles::basics::Vector4::X --
|
||||||
|
*/
|
||||||
|
Double
|
||||||
Vector4::X()
|
Vector4::X()
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
|
@ -58,7 +84,10 @@ Vector4::Y()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Double&
|
/*
|
||||||
|
* charles::basics::Vector4::Y --
|
||||||
|
*/
|
||||||
|
Double
|
||||||
Vector4::Y()
|
Vector4::Y()
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
|
@ -79,7 +108,7 @@ Vector4::Z()
|
||||||
/*
|
/*
|
||||||
* charles::basics::Vector4::Z --
|
* charles::basics::Vector4::Z --
|
||||||
*/
|
*/
|
||||||
const Double&
|
Double
|
||||||
Vector4::Z()
|
Vector4::Z()
|
||||||
const
|
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* --
|
* charles::basics::Vector4::operator* --
|
||||||
*/
|
*/
|
||||||
Vector4
|
Vector4
|
||||||
Vector4::operator*(const Double& rhs)
|
Vector4::operator*(Double rhs)
|
||||||
const
|
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+ --
|
* charles::basics::Vector4::operator+ --
|
||||||
*/
|
*/
|
||||||
Vector4
|
Vector4
|
||||||
Vector4::operator+(const Vector4& rhs)
|
Vector4::operator+(const Vector4 &rhs)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
return Vector4(*this) += rhs;
|
return Vector4(*this) += rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* charles::basics::Vector4::operator- --
|
||||||
|
*/
|
||||||
|
Vector4
|
||||||
|
Vector4::operator-(const Vector4 &rhs)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return Vector4(*this) -= rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* charles::basics::Vector4::operator+= --
|
* charles::basics::Vector4::operator+= --
|
||||||
*/
|
*/
|
||||||
Vector4&
|
Vector4&
|
||||||
Vector4::operator+=(const Vector4& rhs)
|
Vector4::operator+=(const Vector4 &rhs)
|
||||||
{
|
{
|
||||||
mData[0] += rhs.mData[0];
|
mData[0] += rhs.mData[0];
|
||||||
mData[1] += rhs.mData[1];
|
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-= --
|
* charles::basics::Vector4::operator-= --
|
||||||
*/
|
*/
|
||||||
Vector4&
|
Vector4&
|
||||||
Vector4::operator-=(const Vector4& rhs)
|
Vector4::operator-=(const Vector4 &rhs)
|
||||||
{
|
{
|
||||||
return *this += -rhs;
|
return *this += -rhs;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +289,7 @@ Double
|
||||||
Vector4::Length2()
|
Vector4::Length2()
|
||||||
const
|
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)
|
Vector4::Dot(const Vector4& rhs)
|
||||||
const
|
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&
|
||||||
Vector4::Normalize()
|
Vector4::Normalize()
|
||||||
{
|
{
|
||||||
/* XXX: Is there some way to do this with the Matrix<>::operator/? */
|
return *this /= Length();
|
||||||
const Double len = Length();
|
|
||||||
X() = X() / len;
|
|
||||||
Y() = Y() / len;
|
|
||||||
Z() = Z() / len;
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -221,7 +342,7 @@ Vector4::Normalize()
|
||||||
* charles::basics::operator* --
|
* charles::basics::operator* --
|
||||||
*/
|
*/
|
||||||
Vector4
|
Vector4
|
||||||
operator*(const Double& lhs,
|
operator*(Double lhs,
|
||||||
const Vector4& rhs)
|
const Vector4& rhs)
|
||||||
{
|
{
|
||||||
return rhs * lhs;
|
return rhs * lhs;
|
||||||
|
@ -232,9 +353,9 @@ operator*(const Double& lhs,
|
||||||
* charles::basics::Normalized --
|
* charles::basics::Normalized --
|
||||||
*/
|
*/
|
||||||
Vector4
|
Vector4
|
||||||
Normalized(const Vector4& v)
|
Normalized(Vector4 v)
|
||||||
{
|
{
|
||||||
return Vector4(v).Normalize();
|
return v.Normalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,34 +15,56 @@
|
||||||
namespace charles {
|
namespace charles {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
|
||||||
template<UInt N>
|
/** A 4x1 matrix, used for specifying points and directions in 3D space. */
|
||||||
struct Vector
|
|
||||||
: public Matrix<N,1>
|
|
||||||
{ };
|
|
||||||
|
|
||||||
|
|
||||||
struct Vector4
|
struct Vector4
|
||||||
: public Vector<4>
|
|
||||||
{
|
{
|
||||||
Vector4(const Double& x = 0.0, const Double& y = 0.0, const Double& z = 0.0);
|
Vector4();
|
||||||
Vector4(const Matrix<4,1>& m);
|
Vector4(Double x, Double y, Double z);
|
||||||
|
|
||||||
|
Vector4 &operator=(const Vector4 &rhs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup Component access
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
Double& X();
|
Double& X();
|
||||||
const Double& X() const;
|
Double X() const;
|
||||||
Double& Y();
|
Double& Y();
|
||||||
const Double& Y() const;
|
Double Y() const;
|
||||||
Double& Z();
|
Double& Z();
|
||||||
const Double& Z() const;
|
Double Z() const;
|
||||||
|
|
||||||
#if 0
|
Double &operator()(UInt i);
|
||||||
Vector4 operator*(const Double& rhs) const;
|
Double operator()(UInt i) const;
|
||||||
#endif
|
|
||||||
|
|
||||||
Vector4 operator+(const Vector4& rhs) const;
|
/** Get the underlying C array. */
|
||||||
Vector4& operator+=(const Vector4& rhs);
|
const Double *CArray() const;
|
||||||
Vector4 operator-(const Vector4& rhs) const;
|
/** @} */
|
||||||
Vector4& operator-=(const Vector4& rhs);
|
|
||||||
|
|
||||||
|
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;
|
Vector4 operator-() const;
|
||||||
|
|
||||||
/** Get the length-squared of this vector. */
|
/** Get the length-squared of this vector. */
|
||||||
|
@ -52,30 +74,33 @@ struct Vector4
|
||||||
Double Length() const;
|
Double Length() const;
|
||||||
|
|
||||||
/** Get the dot product of `this` and `rhs`. */
|
/** 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`. */
|
/** Get the cross product of `this` and `rhs`. */
|
||||||
Vector4 Cross(const Vector4& rhs) const;
|
Vector4 Cross(const Vector4& rhs) const;
|
||||||
|
|
||||||
/** Normalize this vector. */
|
/** Normalize this vector. */
|
||||||
Vector4& Normalize();
|
Vector4& Normalize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Double mData[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Scalar multiplication of vectors, with the scalar factor on the left. */
|
/** 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. */
|
/** Normalize a copy of the given vector. */
|
||||||
Vector4 Normalized(const Vector4& v);
|
Vector4 Normalized(Vector4 v);
|
||||||
|
|
||||||
|
|
||||||
Vector4 LinearCombination(const Double k1, const Vector4& v1,
|
Vector4 LinearCombination(Double k1, const Vector4 &v1,
|
||||||
const Double k2, const Vector4& v2,
|
Double k2, const Vector4 &v2,
|
||||||
const Double k3, const Vector4& v3);
|
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 basics */
|
||||||
} /* namespace charles */
|
} /* namespace charles */
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace charles {
|
||||||
* charles::Object::Object --
|
* charles::Object::Object --
|
||||||
*/
|
*/
|
||||||
Object::Object(const Vector4& origin)
|
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()
|
mMaterial()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,7 @@ TEST_F(Matrix4Test, ScalarMultiplication)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(Matrix4Test, SquareMatrixMultiplication)
|
TEST_F(Matrix4Test, MatrixMatrixMultiplication)
|
||||||
{
|
{
|
||||||
const Double p1Expect[] = {1045, 1690, 2735, 4425,
|
const Double p1Expect[] = {1045, 1690, 2735, 4425,
|
||||||
2137, 3454, 5591, 9045,
|
2137, 3454, 5591, 9045,
|
||||||
|
@ -267,20 +267,10 @@ TEST_F(Matrix4Test, SquareMatrixMultiplication)
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
EXPECT_EQ(p2.CArray()[i], p2Expect[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;
|
Matrix4 p1 = m1 * id;
|
||||||
for (UInt i = 0; i < 16; i++) {
|
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);
|
Vector4 v1(1, 2, 3);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue