转自:http://blog.csdn.net/clever101/
最近在看《3D数学基础:图形与游戏开发》。该书第六章实现了一个简单三维向量类。我看了一下代码,发现有些地方是错的,于是做了一些小修改。该三维向量类实现了一些常用的向量运算,如点乘、叉乘等。对此不熟悉的同学可以参考相关线性代数教材。现把源码贴上:
view plaincopy to clipboardprint?
#include <float.h>
//@brief 浮点数比较宏,采用VC的浮点数单精度FLT_EPSILON
#define FLOAT_EQ(x,v) (((v - FLT_EPSILON) < x) && (x <( v + FLT_EPSILON)))
namespace TD_Math
{
class Vector3
{
public:
float x;
float y;
float z;
//@brief 默认构造函数,不执行任何操作
Vector3()
{
zero();// 默认为零向量
}
//@brief 复制构造函数
Vector3(const Vector3 &a):x(a.x),y(a.y),z(a.z){}
//@brief 带参数的构造函数,用三个值完成初始化
Vector3(float fx,float fy,float fz):x(fx),y(fy),z(fz){}
//@brief 重载复制运算符,并返回引用,以实现左值
Vector3& operator = (const Vector3 &a)
{
x = a.x;
y = a.y;
z = a.z;
}
//@brief 重载“==”操作符
bool operator ==(const Vector3 &a)const
{ return (FLOAT_EQ(x,a.x)&&FLOAT_EQ(y,a.y)&&FLOAT_EQ(z,a.z)); }
//@brief 重载“!=”运算符
bool operator !=(const Vector3 &a)const
{
return ((!FLOAT_EQ(x,a.x))||(!FLOAT_EQ(y,a.y))||(!FLOAT_EQ(z,a.z)));
}
//@brief 置为零向量
void zero(){x = y = z = 0.0f;}
//@brief 重载“-”运算符
Vector3 operator - () const {return Vector3(-x,-y,-z);}
//@brief 重载二元“+”运算符
Vector3 operator +(const Vector3 &a) const
{
return Vector3(x+a.x,y+a.y,z+a.z);
}
//@brief 重载二元“-”运算符
Vector3 operator -(const Vector3 &a)const
{
return Vector3(x-a.x,y-a.y,z-a.z);
}
//@brief 与标量的乘法
Vector3 operator *(float a)const
{
return Vector3(x*a,y*a,z*a);
}
//@brief 与标量的除法
Vector3 operator /(float a)const
{
float oneOverA = 1.0f/a; // 注意:这里不对“除零”进行检查
return Vector3(x*oneOverA,y*oneOverA,z*oneOverA);
}
//@brief 重载自反运算符
Vector3& operator +=(const Vector3 &a)
{
x += a.x;
y += a.y;
z += a.z;
return *this;
}
Vector3& operator -=(const Vector3 &a)
{
x -= a.x;
y -= a.y;
z -= a.z;
return *this;
}
Vector3& operator *=(float a)
{
x*=a;
y*=a;
z*=a;
return *this;
}
Vector3& operator /=(float a)
{
float oneOverA = 1.0f/a;
x*=oneOverA;
y*=oneOverA;
z*=oneOverA;
return *this;
}
//@brief 向量标准化
void normalize()
{
float magsq = x*x+y*y+z*z;
if (magsq>0.0f) // 检查除零
{
float oneOverMag = 1.0f/sqrt(magsq);
x *=oneOverMag;
y *=oneOverMag;
z *=oneOverMag;
}
}
//@brief 向量点乘
float operator *(const Vector3 &a)const
{
return (x*a.x+y*a.y+z*a.z);
}
};
// 非成员函数
//@brief 求向量模
inline float vectorMag(const Vector3 &a)
{
return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
}
//@brief 计算两向量的叉乘
inline Vector3 crossProduct(const Vector3 &a,const Vector3 &b)
{
return Vector3(
a.y*b.z-a.z*b.y,
a.z*b.x-a.x*b.z,
a.x*b.y-a.y*b.x
);
}
//@brief 实现标量左乘
inline Vector3 operator *(float k,const Vector3 &v)
{
return Vector3(k*v.x,k*v.y,k*v.z);
}
//@brief 计算两点间距离
inline float distance(const Vector3 &a,const Vector3 &b)
{
float dx = a.x-b.x;
float dy = a.y-b.y;
float dz = a.z-b.z;
return sqrt(dx*dx+dy*dy+dz*dz);
}
//@brief 提供一个全局零向量
extern const Vector3 kZeroVector;
}
#include <float.h>
//@brief 浮点数比较宏,采用VC的浮点数单精度FLT_EPSILON
#define FLOAT_EQ(x,v) (((v - FLT_EPSILON) < x) && (x <( v + FLT_EPSILON)))
namespace TD_Math
{
class Vector3
{
public:
float x;
float y;
float z;
//@brief 默认构造函数,不执行任何操作
Vector3()
{
zero();// 默认为零向量
}
//@brief 复制构造函数
Vector3(const Vector3 &a):x(a.x),y(a.y),z(a.z){}
//@brief 带参数的构造函数,用三个值完成初始化
Vector3(float fx,float fy,float fz):x(fx),y(fy),z(fz){}
//@brief 重载复制运算符,并返回引用,以实现左值
Vector3& operator = (const Vector3 &a)
{
x = a.x;
y = a.y;
z = a.z;
}
//@brief 重载“==”操作符
bool operator ==(const Vector3 &a)const
{ return (FLOAT_EQ(x,a.x)&&FLOAT_EQ(y,a.y)&&FLOAT_EQ(z,a.z)); }
//@brief 重载“!=”运算符
bool operator !=(const Vector3 &a)const
{
return ((!FLOAT_EQ(x,a.x))||(!FLOAT_EQ(y,a.y))||(!FLOAT_EQ(z,a.z)));
}
//@brief 置为零向量
void zero(){x = y = z = 0.0f;}
//@brief 重载“-”运算符
Vector3 operator - () const {return Vector3(-x,-y,-z);}
//@brief 重载二元“+”运算符
Vector3 operator +(const Vector3 &a) const
{
return Vector3(x+a.x,y+a.y,z+a.z);
}
//@brief 重载二元“-”运算符
Vector3 operator -(const Vector3 &a)const
{
return Vector3(x-a.x,y-a.y,z-a.z);
}
//@brief 与标量的乘法
Vector3 operator *(float a)const
{
return Vector3(x*a,y*a,z*a);
}
//@brief 与标量的除法
Vector3 operator /(float a)const
{
float oneOverA = 1.0f/a; // 注意:这里不对“除零”进行检查
return Vector3(x*oneOverA,y*oneOverA,z*oneOverA);
}
//@brief 重载自反运算符
Vector3& operator +=(const Vector3 &a)
{
x += a.x;
y += a.y;
z += a.z;
return *this;
}
Vector3& operator -=(const Vector3 &a)
{
x -= a.x;
y -= a.y;
z -= a.z;
return *this;
}
Vector3& operator *=(float a)
{
x*=a;
y*=a;
z*=a;
return *this;
}
Vector3& operator /=(float a)
{
float oneOverA = 1.0f/a;
x*=oneOverA;
y*=oneOverA;
z*=oneOverA;
return *this;
}
//@brief 向量标准化
void normalize()
{
float magsq = x*x+y*y+z*z;
if (magsq>0.0f) // 检查除零
{
float oneOverMag = 1.0f/sqrt(magsq);
x *=oneOverMag;
y *=oneOverMag;
z *=oneOverMag;
}
}
//@brief 向量点乘
float operator *(const Vector3 &a)const
{
return (x*a.x+y*a.y+z*a.z);
}
};
// 非成员函数
//@brief 求向量模
inline float vectorMag(const Vector3 &a)
{
return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
}
//@brief 计算两向量的叉乘
inline Vector3 crossProduct(const Vector3 &a,const Vector3 &b)
{
return Vector3(
a.y*b.z-a.z*b.y,
a.z*b.x-a.x*b.z,
a.x*b.y-a.y*b.x
);
}
//@brief 实现标量左乘
inline Vector3 operator *(float k,const Vector3 &v)
{
return Vector3(k*v.x,k*v.y,k*v.z);
}
//@brief 计算两点间距离
inline float distance(const Vector3 &a,const Vector3 &b)
{
float dx = a.x-b.x;
float dy = a.y-b.y;
float dz = a.z-b.z;
return sqrt(dx*dx+dy*dy+dz*dz);
}
//@brief 提供一个全局零向量
extern const Vector3 kZeroVector;
}
参考文献:
1. 3D数学基础:图形与游戏开发,作者: 邓恩,译者: 陈洪 / 史银雪 / 王荣静
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/clever101/archive/2010/11/30/6046662.aspx