⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vmath

📁 赫赫大名的 OGRE 游戏引擎
💻
📖 第 1 页 / 共 3 页
字号:
// ---------------------------------------------------------------------------------------------------------------------------------
//                        _   _
//                       | | | |
// __   ___ __ ___   __ _| |_| |__
// \ \ / / '_ ` _ \ / _` | __| '_ \
//  \ V /| | | | | | (_| | |_| | | |
//   \_/ |_| |_| |_|\__,_|\__|_| |_|
//
// Description:
//
//   Generic 2-dimensional NxM matrix/vector mathematics class specialized for 3D usage
//
// Notes:
//
//   Best viewed with 8-character tabs and (at least) 132 columns
//
// History:
//
//   04/13/2001 by Paul Nettle: Original creation
//
// Restrictions & freedoms pertaining to usage and redistribution of this software:
//
//   This software is 100% free. If you use this software (in part or in whole) you must credit the author. This software may not be
//   re-distributed (in part or in whole) in a modified form without clear documentation on how to obtain a copy of the original
//   work. You may not use this software to directly or indirectly cause harm to others. This software is provided as-is and without
//   warrantee -- Use at your own risk. For more information, visit HTTP://www.FluidStudios.com/
//
// IMPORTANT:
//
//   Due to the nature of this class being a single solution for all 2D matrices of NxM size (which includes matrices, vectors &
//   points) there are two cases where the class's behavior does not make as much sense as you might like. These two cases are in
//   reference to the >> and ^ operators.
//
//   A multiplication operator is commonly used for component-wise multiplication, dot products and matrix concatenation. Since the
//   class supports the operators [+, -, /, *, +=, -=, /=, *=] it was prudent to maintain consistency and let operator* and
//   operator *= work as component-wise multiplication. So what operators should be used for dot products and concatenation? I have
//   chosen >> for concatenation, because it helps to serve as a reminder in which direction the operation's associativity goes
//   (from left-to-right). The dot product uses operator ^ (simply for lack of a better operator.)
//
//   The problem you may find then, is that operator >> and operator ^ have lower precedence than addition & subtraction. Without
//   the use of parenthesis around these multiplicative operations, you will not get the result you expect.
//
//   Furthermore, operator ^ (dot product) has a lower precedence than even operators [<, <=, >, >=]. This can cause prolems in
//   cases like: "if (v1 ^ v2 > 0)".
//
//   If you do not like the operators I have chosen, feel free to modify them. Or you may chose to perform these operations through
//   the function calls dot(), concat(), cross(), etc.
//
//   Consider yourself warned.
//
// Copyright 2001, Fluid Studios, Inc., all rights reserved.
// ---------------------------------------------------------------------------------------------------------------------------------

#ifndef	_GEOM_VMATH
#define _GEOM_VMATH

// ---------------------------------------------------------------------------------------------------------------------------------
// Module setup (required includes, macros, etc.)
// ---------------------------------------------------------------------------------------------------------------------------------

#include <cmath>
#include "common"
#include "../../Include/fstl/fstl"

GEOM_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------------------------------------------------------------
// Define a matrix that is N columns wide and M rows tall. This matrix is row-major.
//
// N can be thought of as the [N]umber of elements per vector, and M can be thought of as the number of vectors in the matrix
// ---------------------------------------------------------------------------------------------------------------------------------

template <unsigned int N, unsigned int M, class T = GEOM_TYPE>
class	Matrix
{
public:
				// Default constructor

inline				Matrix() {}

				// Copy constructor

inline				Matrix(const Matrix & m)
				{
					fstl::memcpy(_data, m._data, N*M);
				}

				// Initialize with three vectors

inline				Matrix(const Matrix<N, 1, T> & xv, const Matrix<N, 1, T> & yv, const Matrix<N, 1, T> & zv)
				{
					setXVector(xv);
					setYVector(yv);
					setZVector(zv);
				}

				// Initialize with four values (useful for vectors)

inline				Matrix(const T & xv, const T & yv, const T & zv, const T & wv)
				{
					// This assertion guarantees that they are initializing the entire vector

					TemplateAssert(N == 4 && M == 1);

					x() = xv;
					y() = yv;
					z() = zv;
					w() = wv;
				}

				// Initialize with three values (useful for vectors)

inline				Matrix(const T & xv, const T & yv, const T & zv)
				{
					// This assertion guarantees that they are initializing the entire vector

					TemplateAssert(N == 3 && M == 1);

					x() = xv;
					y() = yv;
					z() = zv;
				}

				// Initialize with two values (useful for vectors)

inline				Matrix(const T & xv, const T & yv)
				{
					// This assertion guarantees that they are initializing the entire vector

					TemplateAssert(N == 2 && M == 1);

					x() = xv;
					y() = yv;
				}

				// These are handy 2D/3D/4D casts

inline				operator Matrix<2, 1, T>()
				{
					TemplateAssert(M == 1);

					Matrix<2, 1, T>	result;
					result.fill(0);
					
					int	c = N;
					if (c > 2) c = 2;

					for (int i = 0; i < c; i++) result(i,0) = (*this)(i,0);
					return result;
				}

inline				operator Matrix<3, 1, T>()
				{
					TemplateAssert(M == 1);

					Matrix<3, 1, T>	result;
					result.fill(0);
					
					int	c = N;
					if (c > 3) c = 3;

					for (int i = 0; i < c; i++) result(i,0) = (*this)(i,0);
					return result;
				}

inline				operator Matrix<4, 1, T>()
				{
					TemplateAssert(M == 1);

					Matrix<4, 1, T>	result;
					result.fill(0);
					result.w() = static_cast<T>(1);
					
					int	c = N;
					if (c > 4) c = 4;

					for (int i = 0; i < c; i++) result(i,0) = (*this)(i,0);
					return result;
				}

				// Return a zero'd matrix

static		Matrix		zero()
				{
					Matrix	result;
					result.fill(static_cast<T>(0));
					return result;
				}

				// The infamous 'operator='

inline		Matrix &	operator =(const Matrix & m)
				{
					if (&m != this) fstl::memcpy(_data, m._data, N*M);
					return *this;
				}

				// Indexing: format = i down, j across

inline	const	T &		operator()(const unsigned int i, const unsigned int j) const
				{
					return _data[j*N+i];
				}

				// Indexing: format = i down, j across

inline		T &		operator()(const unsigned int i, const unsigned int j)
				{
					return _data[j*N+i];
				}

				// Matrix concatenation
				//
				// Specialized to follow the rules of matrix multiplication, for NxM * OxP:
				//   where M must be equal to O and resulting matrix is NxP. Otherwise, a
				//   compiler error will occur.
				//
				// Note that we use the >> operator. This is because of the lack of available
				//   operators, and also it serves as a reminder that the operations are from
				//   left-to-right (the convenient way.)

// I'm pretty sure this is wrong (I've seen it crash), so it's conditionally compiled out. Although, given the time, I would
// like to do things this way instad...
#if	0
template <unsigned int P>
inline	const	Matrix<N, P, T>	operator >>(const Matrix<M, P, T> & m) const	{return concat(m);}
template <unsigned int P>
inline	const	Matrix<N, P, T>	operator >>=(const Matrix<M, P, T> & m)		{*this = concat(m); return *this;}
template <unsigned int P>
inline	const	Matrix<N, P, T>	concat(const Matrix<M, P, T> & m) const
				{
					Matrix<N, P, T>	result;
					result.fill(static_cast<T>(0));

					for (unsigned int i = 0; i < N; i++)
					for (unsigned int j = 0; j < M; j++)
					for (unsigned int k = 0; k < P; k++)
					result(i,j) += (*this)(i,k) * m(k,j);

					return result;
				}
#else
// We're doing matrix*vector, which, as far as I can tell, doesn't work the same as vector*vector. Though, it would work the same
// if it was vector*matrix... so this sucker is specialized for that purpose

inline	const	Matrix<N, 1, T>	operator >>(const Matrix<M, 1, T> & m) const	{return concat(m);}
inline	const	Matrix<N, 1, T>	operator >>=(const Matrix<M, 1, T> & m)		{*this = concat(m); return *this;}
inline	const	Matrix<N, 1, T>	concat(const Matrix<M, 1, T> & m) const
				{
					Matrix<N, 1, T>	result;
					result.fill(static_cast<T>(0));

					for (unsigned int i = 0; i < N; i++)
					for (unsigned int j = 0; j < M; j++)
					result(i,0) += (*this)(j,i) * m(j,0);

					return result;
				}

inline	const	Matrix<N, 2, T>	operator >>(const Matrix<M, 2, T> & m) const	{return concat(m);}
inline	const	Matrix<N, 2, T>	operator >>=(const Matrix<M, 2, T> & m)		{*this = concat(m); return *this;}
inline	const	Matrix<N, 2, T>	concat(const Matrix<M, 2, T> & m) const
				{
					Matrix<N, 2, T>	result;
					result.fill(static_cast<T>(0));

					for (unsigned int i = 0; i < N; i++)
					for (unsigned int j = 0; j < M; j++)
					for (unsigned int k = 0; k < 2; k++)
					result(i,j) += (*this)(i,k) * m(k,j);

					return result;
				}

inline	const	Matrix<N, 3, T>	operator >>(const Matrix<M, 3, T> & m) const	{return concat(m);}
inline	const	Matrix<N, 3, T>	operator >>=(const Matrix<M, 3, T> & m)		{*this = concat(m); return *this;}
inline	const	Matrix<N, 3, T>	concat(const Matrix<M, 3, T> & m) const
				{
					Matrix<N, 3, T>	result;
					result.fill(static_cast<T>(0));

					for (unsigned int i = 0; i < N; i++)
					for (unsigned int j = 0; j < M; j++)
					for (unsigned int k = 0; k < 3; k++)
					result(i,j) += (*this)(i,k) * m(k,j);

					return result;
				}

inline	const	Matrix<N, 4, T>	operator >>(const Matrix<M, 4, T> & m) const	{return concat(m);}
inline	const	Matrix<N, 4, T>	operator >>=(const Matrix<M, 4, T> & m)		{*this = concat(m); return *this;}
inline	const	Matrix<N, 4, T>	concat(const Matrix<M, 4, T> & m) const
				{
					Matrix<N, 4, T>	result;
					result.fill(static_cast<T>(0));

					for (unsigned int i = 0; i < N; i++)
					for (unsigned int j = 0; j < M; j++)
					for (unsigned int k = 0; k < 4; k++)
					result(i,j) += (*this)(i,k) * m(k,j);

					return result;
				}
#endif
				// 3D Vector cross product
				//
				// Note that the cross product is specifically a 3-dimensional operation. So this routine
				// will fill the remaining elements (if any) with the contents of this->_data[...]
				//
				// Specialized for Nx1 matrices (i.e. vectors)

inline		void		cross(const Matrix<N, 1, T> & m)
				{
					TemplateAssert(N >= 3);

					T	tx = y() * m.z() - z() * m.y();
					T	ty = z() * m.x() - x() * m.z();
					T	tz = x() * m.y() - y() * m.x();
					x() = tx;
					y() = ty;
					z() = tz;
				}

inline	const	Matrix<N, 1, T>	operator %(const Matrix<N, 1, T> & m) const
				{
					Matrix<N, 1, T>	result = *this;
					result.cross(m);
					return result;
				}

inline	const	Matrix		operator %=(const Matrix & m)
				{
					cross(m);
					return *this;
				}

				// Vector dot product
				//
				// Specialized for Nx1 matrices (i.e. vectors)

inline	const	T		dot(const Matrix<N, 1, T> & m) const
				{
					T	result = static_cast<T>(0);
					for (unsigned int i = 0; i < N; i++) result += _data[i] * m.data()[i];
					return result;
				}

inline	const	T		operator ^(const Matrix<N, 1, T> & m) const
				{
					return dot(m);
				}

				// Component-wise multiplication with matrix

inline	const	Matrix		operator *(const Matrix & m) const
				{
					Matrix	result;
					for (unsigned int i = 0; i < N*M; i++) result._data[i] = _data[i] * m._data[i];
					return result;
				}

				// Component-wise multiplication with scalar

inline	const	Matrix		operator *(const T & value) const
				{
					Matrix	result;
					for (unsigned int i = 0; i < N*M; i++) result._data[i] = _data[i] * value;
					return result;
				}

				// Component-wise multiplication with matrix (into self)

inline	const	Matrix		operator *=(const Matrix & m)
				{
					for (unsigned int i = 0; i < N*M; i++) _data[i] *= m._data[i];
					return *this;
				}

				// Component-wise multiplication with scalar (into self)

inline	const	Matrix		operator *=(const T & value)
				{
					for (unsigned int i = 0; i < N*M; i++) _data[i] *= value;
					return *this;
				}

				// Component-wise division with matrix

inline	const	Matrix		operator /(const Matrix & m) const
				{
					Matrix	result;
					for (unsigned int i = 0; i < N*M; i++) result._data[i] = _data[i] / m._data[i];
					return result;
				}

				// Component-wise division with scalar

inline	const	Matrix		operator /(const T & value) const
				{
					Matrix	result;
					for (unsigned int i = 0; i < N*M; i++) result._data[i] = _data[i] / value;
					return result;
				}

				// Component-wise division with scalar (scalar / component)

inline	const	Matrix		inverseDivide(const T & value) const
				{
					Matrix	result;
					for (unsigned int i = 0; i < N*M; i++) result._data[i] = value / _data[i];
					return result;
				}

				// Component-wise division with matrix (into self)

inline	const	Matrix		operator /=(const Matrix & m)
				{
					for (unsigned int i = 0; i < N*M; i++) _data[i] /= m._data[i];
					return *this;
				}

				// Component-wise division with scalar (into self)

inline	const	Matrix		operator /=(const T & value)
				{
					for (unsigned int i = 0; i < N*M; i++) _data[i] /= value;
					return *this;
				}

				// Component-wise addition with matrix

inline	const	Matrix		operator +(const Matrix & m) const
				{
					Matrix	result;
					for (unsigned int i = 0; i < N*M; i++) result._data[i] = _data[i] + m._data[i];
					return result;
				}

				// Component-wise addition with scalar

inline	const	Matrix		operator +(const T & value) const
				{
					Matrix	result;
					for (unsigned int i = 0; i < N*M; i++) result._data[i] = _data[i] + value;
					return result;
				}

				// Component-wise addition with matrix (into self)

inline	const	Matrix		operator +=(const Matrix & m)
				{
					for (unsigned int i = 0; i < N*M; i++) _data[i] += m._data[i];
					return *this;
				}

				// Component-wise addition with scalar (into self)

inline	const	Matrix		operator +=(const T & value)
				{
					for (unsigned int i = 0; i < N*M; i++) _data[i] += value;
					return *this;
				}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -